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

发布于 2024-09-13 04:44:56 字数 1225 浏览 7 评论 0原文

我有一个 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 任务

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


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

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

如果这看起来是一种合理的做事方式,或者我是否错过了什么?

I have a Silverlight 3 project with something like this:

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

Basically I've added a PNG file to my project and set its build action to "Content". This works nicely.

Now what I'd like to do is be able to add images in a different format to my project, and have them converted to PNG at build time - so that the end result is as if I had added a PNG image to the project (as Content) in the first place.

In other words - I want the image to appear, in PNG format, in my XAP package.

Ideally I would like to do this in such a way that it will work with Visual Web Developer 2008 Express (so I can add image files to my project by dragging them into the IDE and maybe changing their build action), and without making any system-wide changes.

The specific format I want to convert is XCF - I already have the .NET code to do the conversion to PNG. I am assuming that I must create a MSBuild Task.

I don't really have much MSBuild experience, and I'd like to know how to put such a thing together.


Based on my rough understanding of how MSBuild works, I think that I need to know:

  • How to create a collection of items by (re)moving them from the @(Content) (or some other) collection, based on their file extension?
    • OR: Create a custom Build Action I can use in Visual Web Developer 2008 Express
  • How to recieve the path of input items in a Task?
  • Where (.NET or MSBuild?) and How to specify the location of output files generated by a Task?
  • How to ensure that a file is rebuilt if its input file changes?
  • Where (probably BeforeBuild?) and How to reinject the converted items into @(Content)? (Or should I use some other collection?)
    • OR: Some other way of getting them into the XAP?

And if this seems like a reasonable way to do things or if I've missed anything?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伴随着你 2024-09-20 04:44:56

为了实现您的总体目标,您提出了具体的子问题,我想您想了解 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 "%(Sublist.FullPath)"  "%(Sublist.RootDir)%(Sublist.Directory)%(Sublist.Filename).png"" />    

如果 jpg 发生变化(或被清理),如何重建 png。

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

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

最后,您正确地发现了您需要将生成的 .png 文件重新注入到 @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 ...

You have asked specific sub-questions with a view to achieving your overall goal, I presume you want to learn about MSBuild, rather than get a rote answer to your overall task (which is what you are gonna get from many other people due to your bounty), so I will answer your individual questions and then attempt to roll them all up into a solution.

So let's say you want to convert all .jpg files to .png.

Create a sub-list from the content item list based on extension:

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

Receive the path of the item in a task.

Two ways - depends on the input that your task can accept. This way is like a "foreach" over each item in Sublist, and I would tend to use it with an Exec task:

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

Specifying an output path also depends on the .exe or the task that you are and what an output path means to a particular task:

is it a directory, or just a filename with a different extension. But I'll assume you want to output files with the same name, but a different extension:

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

How to rebuild the png if the jpg changes (or is cleaned).

Well, this is using the Inputs and Outputs attribute of the containing target element where our convert command is executed. Inputs specifies what the source files are, and outputs specifies what the target will produce. MSBuild then compares the datetime of the Inputs with the datetime of the output and if they are out of date, then the outputs get rebuilt

<Target Name="ConvertJpg"  
        Inputs="@(Content)"
        Outputs="@(Content -> '%(RootDir)%(Directory)%(Filename).png' )"
        Condition=" '%(Extension)' == '.jpg' "
  • Inputs says that we want to use the "Content" itemgroup
  • The Condition attribute ensures that we are only working with Content items that end in the .jpg extension
  • The Outputs attribute says that of the inputs that we are working with, we'll be generating files that have similar path and filename, but end with the .png extension

Lastly, you correctly have spotted that you need to re-inject the generated .png files back into the @Content item group - well, that's easy, you just Include them into the Content item. Recall that Sublist contains .jpg files - we want those files but with a .png ending. We also do NOT want the .jpg files in the Content item group once a png has been generated

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

So summing up, your target would looks something like this I believe:

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

By the way, ImageMagik has a command line tool that will convert jpg to png...

一身骄傲 2024-09-20 04:44:56

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

<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 只是在属性中嵌入引号的一种方法。)

I believe you want something like this:

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

where you specify a new JPGContent BuildAction that it converts.

(Possibly see also http://msdn.microsoft.com/en-us/library/ms164313.aspx and note that %22 is just a way to embed a quotation mark in an attribute.)

无声情话 2024-09-20 04:44:56

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

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

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

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

示例实现可以在以下位置找到
http://www.drewnoakes.com/snippets/WritingACustomCodeGeneratorToolForVisualStudio/

Instead of creating a MSBuild task you can also create a Custom tool and specify this in Custom Tool in properties of your image file.

"a custom tool will transform a file at design time and will place the output of the transformation into another file"

e.g. DataSet. it has its own transformation tool through which we get a class to use in our application.

the advantage of this approach is you
can use the generated file at design
time as well.

as sample implementation can be found at
http://www.drewnoakes.com/snippets/WritingACustomCodeGeneratorToolForVisualStudio/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文