7

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

<ItemGroup>
  <Content Include="Content\image1.png">
  </Content>
</ItemGroup>

基本上我已经在我的项目中添加了一个 PNG 文件并将其构建操作设置为“内容”。这很好用。

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

换句话说 - 我希望图像以 PNG 格式出现在我的 XAP 包中。

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

我要转换的具体格式是 XCF——我已经有了 .NET 代码来转换为 PNG。我假设我必须创建一个 MSBuild Task

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


根据我对 MSBuild 工作原理的粗略理解,我认为我需要知道:

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

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

4

3 回答 3

13

您已经提出了具体的子问题以实现您的总体目标,我想您想了解 MSBuild,而不是对您的整体任务获得死记硬背的答案(由于您的赏金),所以我将回答您的个人问题,然后尝试将它们全部汇总到一个解决方案中。

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

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

<ItemGroup>
    <Sublist Include="@(Content)" Condition=" '%(Extension)' == '.jpg' " />
</ItemGroup>

接收任务中项目的路径。

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

<Exec Command="convert.exe /Input:%(Sublist.FullPath)" />

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

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

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

如果 jpg 更改(或已清理),如何重建 png。

好吧,这是使用包含目标元素的 Inputs 和 Outputs 属性,我们的转换命令在其中执行。输入指定源文件是什么,输出指定目标将产生什么。MSBuild 然后将输入的日期时间与输出的日期时间进行比较,如果它们已过期,则重新构建输出

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

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

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

综上所述,我相信你的目标看起来像这样:

<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>

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

于 2010-08-10T09:29:05.870 回答
2

我相信你想要这样的东西:

<ItemGroup>
  <JPGContent Include="foo.jpg" />
</ItemGroup>
<Target Name="BeforeBuild" 
        Inputs="@(JPGContent)" Outputs="%(JPGContent.Filename).png">
  <!-- replace this with call to jpg->png converter -->
  <Exec Command="copy %22%(JPGContent.FullPath)%22 %(JPGContent.Filename).png" />
  <ItemGroup>
    <Content Include="%(JPGContent.Filename).png" />
  </ItemGroup>
</Target>
<Target Name="AfterBuild">
  <!-- just demoing that 'Content' now has right value -->
  <Warning Text ="Content=@(Content)" />
</Target>

您可以在其中指定JPGContent它转换的新 BuildAction。

(可能另请参阅http://msdn.microsoft.com/en-us/library/ms164313.aspx并注意这%22只是在属性中嵌入引号的一种方式。)

于 2010-08-10T08:11:10.213 回答
0

除了创建 MSBuild 任务,您还可以创建自定义工具并在图像文件属性中的自定义工具中指定它。

“自定义工具将在设计时转换文件并将转换的输出放入另一个文件”

例如数据集。它有自己的转换工具,通过它我们可以在我们的应用程序中使用一个类。

这种方法的优点是您也可以在设计时使用生成的文件。

作为示例实现可以在 http://www.drewnoakes.com/snippets/WritingACustomCodeGeneratorToolForVisualStudio/找到

于 2010-08-10T08:09:08.487 回答