MSBuild:如何在构建时创建和使用任务来转换内容项?

And*_*ell 7 msbuild silverlight msbuild-task visual-studio

我有一个类似这样的Silverlight 3项目:

<ItemGroup>
  <Content Include="Content\image1.png">
  </Content>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

基本上我已经将PNG文件添加到我的项目中,并将其构建操作设置为"内容".这很好用.

现在我想做的是能够以不同的格式将图像添加到我的项目中,并在构建时将它们转换为PNG - 这样最终结果就好像我已经将PNG图像添加到项目中一样(作为内容)首先.

换句话说 - 我希望图像以PNG格式显示在我的XAP包中.

理想情况下,我希望这样做,它将与Visual Web Developer 2008 Express一起使用(因此我可以通过将图像文件拖入IDE并可能更改其构建操作来将图像文件添加到我的项目中),而无需制作任何系统全面的变化.

我想要转换的特定格式是XCF - 我已经有.NET代码来转换为PNG.我假设我必须创建一个MSBuild任务.

我没有太多的MSBuild经验,我想知道如何把这样的东西放在一起.


基于我对MSBuild如何工作的粗略理解,我认为我需要知道:

  • 如何@(Content)根据文件扩展名(重新)从(或其他)集合中移动它们来创建项目集合?
    • 或者:创建我可以在Visual Web Developer 2008 Express中使用的自定义构建操作
  • 如何接收输入项的路径Task
  • 哪里(.NET或MSBuild?)和如何指定生成的输出文件的位置Task
  • 如果文件的输入文件发生变化,如何确保重建文件?
  • 在哪里(可能BeforeBuild?)以及如何将转换后的项目重新注入@(Content)?(或者我应该使用其他一些系列?)
    • 或者:将其纳入XAP的其他方式?

如果这似乎是一种合理的做事方式,或者我错过了什么?

Pet*_*voy 13

您已经询问了具体的子问题以实现您的总体目标,我认为您想要了解MSBuild,而不是对您的整体任务得到一个死记硬背的答案(这是您将从许多其他人那里获得的,因为您的赏金),所以我会回答你的个别问题,然后尝试将它们全部解决.

因此,假设您要将所有.jpg文件转换为.png.

根据扩展名从内容项列表创建子列表:

<ItemGroup>
    <Sublist Include="@(Content)" Condition=" '%(Extension)' == '.jpg' " />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

接收任务中项目的路径.

两种方式 - 取决于您的任务可以接受的输入.这种方式就像是子列表中每个项目的"foreach",我倾向于将它与Exec任务一起使用:

<Exec Command="convert.exe /Input:%(Sublist.FullPath)" />
Run Code Online (Sandbox Code Playgroud)

指定输出路径还取决于.exe或您的任务以及输出路径对特定任务的含义:

它是一个目录,还是只是一个具有不同扩展名的文件名.但我假设您要输出具有相同名称但扩展名不同的文件:

<Exec Command="convert.exe &quot;%(Sublist.FullPath)&quot;  &quot;%(Sublist.RootDir)%(Sublist.Directory)%(Sublist.Filename).png&quot;" />    
Run Code Online (Sandbox Code Playgroud)

如果jpg改变(或清理),如何重建png.

好吧,这是使用包含目标元素的Inputs and Outputs属性执行convert命令的地方.输入指定源文件是什么,输出指定目标将生成的内容.然后,MSBuild将输入的日期时间与输出的日期时间进行比较,如果它们已过期,则输出将重建

<Target Name="ConvertJpg"  
        Inputs="@(Content)"
        Outputs="@(Content -> '%(RootDir)%(Directory)%(Filename).png' )"
        Condition=" '%(Extension)' == '.jpg' "
Run Code Online (Sandbox Code Playgroud)
  • 输入说我们想要使用"内容"项目组
  • Condition属性确保我们仅处理以.jpg扩展名结尾的内容项
  • Outputs属性表示我们正在使用的输入,我们将生成具有相似路径和文件名的文件,但以.png扩展名结尾

最后,您正确地发现需要将生成的.png文件重新注入@Content项目组 - 嗯,这很简单,您只需将它们包含在Content项中.回想一下,Sublist包含.jpg文件 - 我们想要这些文件但是.png结尾.一旦生成了png,我们也不希望内容项组中的.jpg文件

<Content Remove="@(Sublist)" />
<Content Include="@(Sublist -> '%(RootDir)%(Directory)%(Filename).png' )" />
Run Code Online (Sandbox Code Playgroud)

所以总结一下,你的目标看起来像我相信:

<Target Name="ConvertJpg"  
        Inputs="@(Content)"
        Outputs="@(Content -> '%(RootDir)%(Directory)%(Filename).png' )"
        Condition=" '%(Extension)' == '.jpg' "
    <ItemGroup>
        <Sublist Include="@(Content)" Condition=" '%(Extension)' == '.jpg' " />
    </ItemGroup>

    <Exec Command="convert.exe /Input:%(Sublist.FullPath) Output=%(Sublist.RootDir)%(Sublist.Directory)%(Sublist.Filename).png" />

    <Content Remove="@(Sublist)" />
    <Content Include="@(Sublist -> '%(RootDir)%(Directory)%(Filename).png' )" />
</Target>
Run Code Online (Sandbox Code Playgroud)

顺便说一下,ImageMagik有一个命令行工具,可以将jpg转换为png ...