我经常在ASP.NET项目中添加很多内容文件(主要是图像和js)。我正在使用VS发布系统,并且在发布时,直到将新文件包含在项目中之后,才会发布新文件。我想自动包含指定目录中的所有文件。有没有一种方法可以指定哪些目录应自动包含在csproj文件或其他任何地方?
Answers:
我知道老线程,但是我找到了一种方法,但我一直忘了它,而在上次寻找它的搜索中,我偶然发现了这个问题。我发现最好的方法是使用.csproj文件中的BeforeBuild目标。
<Target Name="BeforeBuild">
<ItemGroup>
<Content Include="**\*.less" />
</ItemGroup>
</Target>
VS 2010不会涉及此部分,它可确保每次构建项目时文件都作为内容包含在内。
**\*.less
?
**\*.less
表示在所有目录中包括所有* .less文件。用MSBUILD讲,**表示“所有目录都递归”
您只需扩展您的网站.csproj文件即可。只需使用递归通配符添加内容根文件夹:
...
<ItemGroup>
<!-- your normal project content -->
<Content Include="Default.aspx" />
<!-- your static content you like to publish -->
<Content Include="Images\**\*.*" />
</ItemGroup>
...
这样做会使此文件夹以及下面的所有内容在解决方案浏览器中可见。
如果您尝试通过指定隐藏解决方案浏览器中的文件夹
<Content Include="Images\**.*.*">
<Visible>false</Visible>
</Content>
它不会被发布。
更新资料
正如您已经发现的那样,一旦您触摸解决方案中的文件夹,通配符将被替换,因为VS项目并非旨在包含任意内容。
因此,您必须确保文件夹和其内容绝不会在VS内进行修改-添加或删除文件只能在文件系统上进行...这就是您想要的,因为我了解您的问题。
如果该文件夹可以在VS中隐藏,但我找不到隐藏它并发布的方法,将会更容易。
另一种不成功的方法是按CreateItem
任务包含文件夹。这导致该文件夹的内容被发布到\ bin \ app.publish \ ...,并且无法说服将其与.csproj中的内容项一起发布,因此我没有在回答中给出它。
<Content Include="Images\**\*.*" />
后有效。添加更多图像后,.csproj便会更改,并返回列出图像中的所有文件/ ...,<Content Include =“ Images * *。 ” />消失了。
对于使用Chris的答案有问题的人,这是Visual Studio 2012及更高版本的解决方案:
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild">
<ItemGroup>
<Content Include="images\**" />
</ItemGroup>
</Target>
克里斯(Chris)在回答中提到-即使您手动在目标目录中随意<Target>
摆弄(添加/删除文件),Visual Studio也不会涉及到此部分。
请注意,您应该在其中包含文件的子目录(在上述情况下为images
)。Visual Studio / MSBuild会将这些文件放在项目结构内的同一目录中。如果不使用子目录,则文件将放置在项目结构的根目录下。
有关通配符的快速说明:
**
递归地表示所有内容(文件,子目录和其中的文件)*.ext
将ext
在顶层目录中包含所有带有扩展名的文件,但不包括子目录
*.ext
可能是*.png
,*.js
等。任何文件扩展名都可以使用**\*.ext
将包括ext
顶级目录和所有子目录中所有带有扩展名的文件。为了完成操作,请注意,使用<Target>
和不使用它是有区别的。
通过这种<Target>
方法,Visual Studio将不会在解决方案资源管理器中显示文件。
<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild">
<ItemGroup>
<Content Include="images\**" />
</ItemGroup>
</Target>
非<Target>
方法将指示Visual Studio在解决方案资源管理器中显示文件。这样做的缺点是,对自动目录的任何操作都会导致Visual Studio覆盖通配符条目。还应注意,以下方法仅在VS中打开“解决方案/项目”后才会更新“解决方案资源管理器”。甚至解决方案资源管理器的“刷新”工具栏按钮也不会执行此操作。
<ItemGroup>
<Content Include="images\**" />
</ItemGroup>
BeforeBuild
?MSBuild必须首先构建项目和二进制文件,然后才能考虑发布。
.. AfterTargets="BeforeBuild"
。意思是,您的自定义目标必须在BeforeBuild之后执行,但是没有指定之后多少。但是,我的错误是,按当前的目标排序算法应该没问题:msdn.microsoft.com/en-us/library/ee216359.aspx
您可以使用框架的System.IO.Directory.GetFile(string)
方法及其重载来递归包括所有文件。
<ItemGroup>
<Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" />
<Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" />
</ItemGroup>
Include="**\*.ext"
与通配符相同的局限性。
我已经写出了如何使用小型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`" /> "
}
这应该在powershell提示符下产生必要的include语句
您可以添加具有以下链接的文件,它们是可搜索的,可查看的,但是如果您尝试更改它们,它们不会签出,而且visual studio会将通配符保留在适当的位置:
<ItemGroup>
<Content Include="..\Database Schema\Views\*.sql">
<Link>Views\*.sql</Link>
</Content>
</ItemGroup>
这位于.proj文件中。