仅使用内容文件创建VS 2010项目

时间:2010-04-27 16:57:37

标签: visual-studio msbuild

我有一些内容文件,我想在Visual Studio中的许多项目之间共享。

我已将这些文件放在他们自己的项目中,将构建操作设置为“Content”,将复制到输出目录设置为“Copy if newer”。我希望将所有这些文件复制到引用它们的项目的bin / debug目录中。

我可以通过在每个需要文件的项目中包含对“contents”项目的引用来实现它,但这需要生成最小的程序集(3K)。我假设使用MSBuild有一种方法可以在不创建空装配的情况下完成所有工作吗?

4 个答案:

答案 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)

更好可能的解决方案是

  • 在解决方案目录中放置一个公共目录,并将公共内容文件放在那里。

  • 在VS中的
  • ,在应该共享此内容的每个项目中,右键单击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

相关问题