Con frecuencia agrego muchos archivos de contenido (principalmente imágenes y js) a mi proyecto ASP.NET. Estoy usando el sistema de publicación VS, y al publicar, los archivos nuevos no se publican hasta que los incluyo en el proyecto. Me gustaría incluir automáticamente todos los archivos en el directorio especificado. ¿Hay alguna forma de especificar qué directorios deben incluirse automáticamente en el archivo csproj o en cualquier otro lugar?
86
Respuestas:
Viejo hilo, lo sé, pero encontré una manera de hacer esto que sigo olvidando, y en mi búsqueda para encontrarlo por última vez, me topé con esta pregunta. La mejor manera que he encontrado para esto es usar el destino BeforeBuild en el archivo .csproj.
<Target Name="BeforeBuild"> <ItemGroup> <Content Include="**\*.less" /> </ItemGroup> </Target>
VS 2010 no tocará esta sección y garantiza que sus archivos se incluyan como contenido cada vez que se compile el proyecto.
fuente
**\*.less
?**\*.less
significa incluir todos los archivos * .less en todos los directorios. En lenguaje MSBUILD, ** significa 'todos los directorios de forma recursiva'Simplemente puede ampliar el archivo .csproj de su sitio web. Simplemente agregue su carpeta raíz de contenido con un comodín recursivo:
... <ItemGroup> <!-- your normal project content --> <Content Include="Default.aspx" /> <!-- your static content you like to publish --> <Content Include="Images\**\*.*" /> </ItemGroup> ...
Si lo hace, esta carpeta y todo el contenido a continuación estarán visibles dentro de su navegador de soluciones.
Si intenta ocultar la carpeta dentro del navegador de soluciones especificando
<Content Include="Images\**.*.*"> <Visible>false</Visible> </Content>
No será publicada.
Actualizar
Como ya descubrió, el comodín se reemplazará tan pronto como toque la carpeta dentro de su solución porque los proyectos de VS no están diseñados para contener contenido arbitrario.
Por lo tanto, deberá asegurarse de que la carpeta y su contenido nunca se modifiquen desde VS; agregar o eliminar archivos solo se puede hacer en el sistema de archivos ... que es lo que quería cuando entendí su pregunta.
Sería más fácil si la carpeta pudiera estar oculta en VS pero no pude encontrar una manera de ocultarla Y publicarla.
Otro enfoque fallido fue incluir la carpeta en una
CreateItem
tarea. Esto dio como resultado que el contenido de la carpeta se publicara en \ bin \ app.publish \ ... y no se me pudo convencer para publicarlo junto con los elementos de contenido dentro del .csproj, por lo que no lo presenté en mi respuesta.fuente
<Content Include="Images\**\*.*" />
funcionó. Una vez que agregas más imágenes, el .csproj cambia y vuelve a listar todos los archivos en las imágenes / ... y el <Contenido Incluido = "Imágenes * *. " /> Desaparece.Para aquellos que tengan problemas para usar la respuesta de Chris , esta es la solución para Visual Studio 2012 y versiones posteriores:
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
Como Chris mencionó en su respuesta, Visual Studio no tocará esto
<Target>
sección, incluso si manipula manualmente (agregando / eliminando archivos) con el directorio de destino.Tenga en cuenta que debe incluir un subdirectorio donde se encuentran los archivos (en el caso anterior, es
images
). Visual Studio / MSBuild colocará esos archivos en el mismo directorio dentro de la estructura del proyecto. Si no usa un subdirectorio, los archivos se colocarán en la raíz de la estructura del proyecto.Para una explicación rápida de los comodines:
**
significa todo de forma recursiva (archivos, subdirectorios y archivos dentro de esos)*.ext
incluirá todos los archivos con extensiónext
dentro del directorio de nivel superior, pero no los subdirectorios*.ext
podría ser*.png
,*.js
etc. Cualquier extensión de archivo funcionará**\*.ext
incluirá todos los archivos con extensiónext
del directorio de nivel superior y todos los subdirectorios.Para completar, tenga en cuenta que hay una diferencia entre usar
<Target>
y no usarlo.Con el
<Target>
enfoque, Visual Studio no mostrará los archivos dentro del Explorador de soluciones.<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild"> <ItemGroup> <Content Include="images\**" /> </ItemGroup> </Target>
El no
<Target>
enfoque indicará a Visual Studio que muestre los archivos dentro del Explorador de soluciones. El inconveniente de este es que cualquier manipulación de los directorios automáticos hará que Visual Studio anule la entrada comodín. También debe tenerse en cuenta que el enfoque a continuación solo actualizará el Explorador de soluciones al abrir la Solución / Proyecto en VS. Incluso el botón de la barra de herramientas "actualizar" del Explorador de soluciones no lo hará.<ItemGroup> <Content Include="images\**" /> </ItemGroup>
fuente
BeforeBuild
evento? MSBuild primero debe compilar el proyecto y los binarios antes de que pueda siquiera considerar la publicación... AfterTargets="BeforeBuild"
. Es decir, su destino personalizado debe ejecutarse después de BeforeBuild, pero no especifica cuánto después. Aunque, mi error, según el algoritmo de pedido de destino actual debería estar bien: msdn.microsoft.com/en-us/library/ee216359.aspxPuede utilizar el
System.IO.Directory.GetFile(string)
método del marco y sus sobrecargas para incluir de forma recursiva todos los archivos.<ItemGroup> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" /> <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" /> </ItemGroup>
fuente
Include="**\*.ext"
con los comodines.He escrito cómo pude hacer que el contenido se creara con un pequeño script de 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`" /> " }
Esto debería producir la declaración de inclusión necesaria en el indicador de PowerShell
fuente
Puede agregar archivos con enlaces como este, se pueden buscar, se pueden ver, pero no se cierran si intenta cambiarlos, también Visual Studio deja los comodines en su lugar:
<ItemGroup> <Content Include="..\Database Schema\Views\*.sql"> <Link>Views\*.sql</Link> </Content> </ItemGroup>
Esto va dentro del archivo .proj.
fuente
No que yo sepa; sin embargo, mi sugerencia es pegarlos en el proyecto, ya que esto los incluirá de forma predeterminada. Entonces, en lugar de pegarlos en el directorio a través del Explorador, use Visual Studio para pegar los archivos en las carpetas.
fuente
Me di cuenta de que la mejor solución para esto es agregar archivos manualmente, uno por uno. Si tienes cientos de ellos como yo, fue solo cuestión de unas pocas horas. Es curioso que incluso en 2016 con VS 2015 este grave problema aún no esté resuelto. Ahh, cómo amo Xcode.
fuente