Freqüentemente, estou adicionando muitos arquivos de conteúdo (principalmente imagens e js) ao meu projeto ASP.NET. Estou usando o sistema de publicação VS e, ao publicar, novos arquivos não são publicados até que eu os inclua no projeto. Eu gostaria de incluir automaticamente todos os arquivos no diretório especificado. Existe uma maneira de especificar quais diretórios devem ser incluídos automaticamente no arquivo csproj ou em qualquer outro lugar?
86
Respostas:
Tópico antigo, eu sei, mas encontrei uma maneira de fazer isso que continuo esquecendo e, em minha busca para encontrá-la pela última vez, tropecei nessa questão. A melhor maneira que descobri para fazer isso é usar o destino BeforeBuild no arquivo .csproj.
<Target Name="BeforeBuild"> <ItemGroup> <Content Include="**\*.less" /> </ItemGroup> </Target>
O VS 2010 não tocará nesta seção e garante que seus arquivos sejam incluídos como conteúdo sempre que o projeto for construído.
fonte
**\*.less
?**\*.less
significa incluir todos os arquivos * .less em todos os diretórios. Em linguagem MSBUILD, ** significa 'todos os diretórios recursivamente'Você simplesmente pode estender o arquivo .csproj do seu site. Basta adicionar sua pasta raiz de conteúdo com um caractere curinga recursivo:
... <ItemGroup> <!-- your normal project content --> <Content Include="Default.aspx" /> <!-- your static content you like to publish --> <Content Include="Images\**\*.*" /> </ItemGroup> ...
Isso torna esta pasta e todo o conteúdo abaixo visíveis dentro do navegador da solução.
Se você tentar ocultar a pasta dentro do navegador da solução, especificando
<Content Include="Images\**.*.*"> <Visible>false</Visible> </Content>
não será publicado.
Atualizar
Como você já descobriu, o curinga será substituído assim que você tocar na pasta dentro de sua solução porque os projetos do VS não são projetados para conter conteúdo arbitrário.
Portanto, você terá que garantir que a pasta e seu conteúdo nunca sejam modificados de dentro do VS - adicionar ou remover arquivos só pode ser feito no sistema de arquivos ... que é o que você queria, pois entendi sua pergunta.
Seria mais fácil se a pasta pudesse estar oculta no VS, mas não consegui encontrar uma maneira de ocultá-la E publicar.
Outra abordagem malsucedida foi incluir a pasta por uma
CreateItem
Tarefa. Isso resultou na publicação do conteúdo da pasta em \ bin \ app.publish \ ... e não pude ser convencido a publicá-lo junto com os itens de conteúdo dentro do .csproj, então não o apresentei em minha resposta.fonte
<Content Include="Images\**\*.*" />
funcionou. Depois de adicionar mais imagens, o .csproj é alterado e volta a listar todos os arquivos nas imagens / ... e <Content Include = "Images * *. " /> Desaparece.Para aqueles que têm problemas para usar a resposta de Chris , esta é a solução para o Visual Studio 2012 e mais recente:
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
Como Chris mencionou em sua resposta - o Visual Studio não tocará nesta
<Target>
seção, mesmo se você mexer manualmente (adicionando / removendo arquivos) com o diretório de destino.Observe que você deve incluir um subdiretório onde os arquivos estão localizados (no caso acima, é
images
). O Visual Studio / MSBuild colocará esses arquivos no mesmo diretório dentro da estrutura do projeto. Se você não usar um subdiretório, os arquivos serão colocados na raiz da estrutura do projeto.Para uma explicação rápida dos curingas:
**
significa tudo recursivamente (arquivos, subdiretórios e arquivos dentro deles)*.ext
irá incluir todos os arquivos com extensãoext
dentro do diretório de nível superior, mas não subdiretórios*.ext
poderia ser*.png
,*.js
etc. Qualquer extensão de arquivo irá funcionar**\*.ext
incluirá todos os arquivos com extensãoext
do diretório de nível superior e todos os subdiretórios.Para completar, observe que há uma diferença entre usá-lo
<Target>
e não usá-lo.Com a
<Target>
abordagem, o Visual Studio não mostrará os arquivos no Solution Explorer.<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
A não
<Target>
abordagem irá instruir o Visual Studio para mostrar os arquivos dentro do Solution Explorer. A desvantagem desse aqui é que qualquer manipulação dos diretórios automáticos fará com que o Visual Studio substitua a entrada curinga. Também deve ser observado que a abordagem abaixo só atualizará o Gerenciador de Soluções ao abrir a Solução / Projeto no VS. Mesmo o botão "atualizar" da barra de ferramentas do Solution Explorer não fará isso.<ItemGroup> <Content Include="images\**" /> </ItemGroup>
fonte
BeforeBuild
evento? O MSBuild deve primeiro criar o projeto e os binários antes mesmo de considerar a publicação... AfterTargets="BeforeBuild"
. Ou seja, seu destino personalizado deve ser executado após BeforeBuild, mas não especifica quanto depois. Porém, erro meu, pelo algoritmo de ordenação de destino atual, deve estar tudo bem: msdn.microsoft.com/en-us/library/ee216359.aspxVocê pode usar o
System.IO.Directory.GetFile(string)
método do framework e suas sobrecargas para incluir recursivamente todos os arquivos.<ItemGroup> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" /> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" /> </ItemGroup>
fonte
Include="**\*.ext"
curingas.Eu escrevi como consegui incluir o conteúdo criado com um pequeno script PowerShell:
$folders = Get-ChildItem .\ -r -Directory $filtered = $folders |Select-Object @{Name='FullName';Expression={$_.fullname.replace($pwd,'')}}, @{Name='FolderDepth';Expression={($_.fullname.Split('\').Count) - ($Pwd.Path.split('\').count)}} | Sort-Object -Descending FullName,folderDepth $basefolders = $filtered | Where-Object{$_.folderdepth -eq 1} $basefoldersobj = @() foreach($basefolder in $basefolders) { $basefoldername =$baseFolder.fullname $filteredbase = $filtered -match "\$basefoldername\\" | Sort-Object -Descending FolderDepth | Select-Object -first 1 if($filteredbase -eq $null) { $filteredbase = $filtered -match "\$basefoldername" | Sort-Object -Descending FolderDepth | Select-Object -first 1 } $obj = New-Object psobject Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Folder' -Value $basefolder.fullname.trim('\') Add-member -InputObject $obj -MemberType NoteProperty -Name 'DeepestPath' -Value $filteredbase.folderDepth $basefoldersobj += $obj } $include = '*.*' foreach($bfolderObj in $basefoldersobj) { $includecount = '' $includecount = "\$include" * ($bfolderObj.Deepestpath) Write-Output "<content Include=`"$($bfolderObj.folder)$includecount`" /> " }
Isso deve produzir a instrução include necessária no prompt do PowerShell
fonte
Você pode adicionar arquivos com links como este, eles podem ser pesquisados, visualizados, mas não são finalizados se você tentar alterá-los. Além disso, o Visual Studio mantém os curingas no lugar:
<ItemGroup> <Content Include="..\Database Schema\Views\*.sql"> <Link>Views\*.sql</Link> </Content> </ItemGroup>
Isso vai dentro do arquivo .proj.
fonte
Não que eu saiba; no entanto, minha sugestão é colá-los no projeto, pois isso os incluirá por padrão. Portanto, em vez de colá-los no diretório por meio do Explorer, use o Visual Studio para colar os arquivos nas pastas.
fonte
Percebi que a melhor solução para isso é adicionar arquivos manualmente, um por um. Se você tem centenas deles como eu, era questão de apenas algumas horas. Engraçado que mesmo em 2016 com o VS 2015 esse sério problema ainda não foi resolvido. Ahh, como eu amo o Xcode.
fonte