我有一些内容文件,我想在Visual Studio中的许多项目之间共享。
我已将这些文件放在他们自己的项目中,将构建操作设置为“Content”,将复制到输出目录设置为“Copy if newer”。我希望将所有这些文件复制到引用它们的项目的bin / debug目录中。
我可以通过在每个需要文件的项目中包含对“contents”项目的引用来实现它,但这需要生成最小的程序集(3K)。我假设使用MSBuild有一种方法可以在不创建空装配的情况下完成所有工作吗?
答案 0 :(得分:4)
感谢有史以来花时间提出如何解决这个问题的建议。
事实证明,如果我希望将编译后的内容文件视为内容文件(因为它们会被复制到引用我项目的任何其他项目的输出目录中),我需要创建一个在GetCopyToOutputDirectoryItems之前运行的目标,并将已编译内容文件的完整路径添加到AllItemsFullPathWithTargetPath ItemGroup。 MSBuild为当前项目所依赖的项目调用GetCopyToOutputDirectoryItems,并使用生成的文件列表来确定与assembly.dll一起复制的文件。这是我的.csproj中的XML,以防其他人遇到类似的问题。
我有一个名为“ZipDictionary”的自定义任务,我在ItemGroup中累积了我要编译的所有文件,名为DictionaryCompile。我的目标“FixGetCopyToOutputDirectoryItems”在“GetCopyToOutputDirectoryItems”之前执行。我没有在那里进行实际的编译,因为这个目标可以通过引用项目多次调用,这会损害性能。目标执行一些转换以获取后编译文件名,然后返回所有文件的完整路径,因为从引用项目调用copy时相对路径将不起作用。
<ItemGroup>
<DictionaryCompile Include="Dictionaries\it-IT.dic">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</DictionaryCompile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="ZipDictionary" AssemblyFile="..\LogicTree.DictionaryCompiler\bin\Debug\LogicTree.DictionaryCompiler.dll"/>
<Target Name="BeforeCompile">
<Message Text="Files @(DictionaryCompile)" Importance="high" />
<ZipDictionary DictionaryFiles="@(DictionaryCompile)" OutputDirectory="$(OutputPath)">
<Output TaskParameter="OutputFiles" ItemName="DictionaryOutputFiles" />
</ZipDictionary>
</Target>
<Target Name="FixGetCopyToOutputDirectoryItems" BeforeTargets="GetCopyToOutputDirectoryItems">
<ItemGroup>
<_DictionaryCompile Include="@(DictionaryCompile->'$(OutputPath)Dictionaries\%(FileName).ltdic')" />
</ItemGroup>
<AssignTargetPath Files="@(_DictionaryCompile)" RootFolder="$(MSBuildProjectDirectory)\$(OutputPath)">
<Output TaskParameter="AssignedFiles" ItemName="_DictionaryCompileWithTargetPath" />
</AssignTargetPath>
<ItemGroup>
<AllItemsFullPathWithTargetPath Include="@(_DictionaryCompileWithTargetPath->'%(FullPath)')" Condition="'%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
<_SourceItemsToCopyToOutputDirectoryAlways Include="@(_DictionaryCompileWithTargetPath->'%(FullPath)')" Condition="'%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='Always'" />
<_SourceItemsToCopyToOutputDirectory Include="@(_DictionaryCompileWithTargetPath->'%(FullPath)')" Condition="'%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
</ItemGroup>
</Target>
答案 1 :(得分:3)
更好可能的解决方案是
在解决方案目录中放置一个公共目录,并将公共内容文件放在那里。
,在应该共享此内容的每个项目中,右键单击add existing item
,浏览到所需的项目,选择,单击add
上的向下箭头按钮并选择add as link
。在项目中,您会注意到文件添加了“快捷方式”覆盖。
在项目中,选择新添加的链接和右键单击 - &gt;属性,然后选择构建操作:内容,复制到输出目录:始终复制。
这是解决问题的简单方法。
我将此技术用于SQL脚本和部分配置文件(使用configSource)等方面取得了巨大成功。这使我可以在一个位置对这些文件进行更改,并确保在整个解决方案中对它们进行预测。
更强大的解决方案是创建包含嵌入资源的项目。这需要更多的工作来管理接收端的内容,但从长远来看可能是值得的,因为有一堆松散的工件可能会成为问题。
希望有所帮助。
答案 2 :(得分:1)
类似天空建议的解决方案可以在my answer to "Is there a way to automatically include content files into asp.net project file?"中找到。
它允许共享您的内容,但您不得触摸VS内的文件夹或其内容,因为这会破坏递归路径。
此方法最适合自动生成的内容 - 您无需为将新内容文件包含在解决方案中而烦恼。
当然,您可以在多个解决方案/项目中重复使用它。
答案 3 :(得分:0)
我们做了类似的事情,我们有“... ReleaseBuilds”,它引用了特定项目所需的dll和内容。编译将所有内容复制到bin调试文件夹,并确实创建了空程序集。
在Visual Studio中,我们在“... RealeaseBuild”(在项目属性中)中有一个后期构建事件,它复制/删除或运行批处理文件以确保我们拥有所需的所有文件(配置,服务等)并删除空组件。
HTH