如何为每次执行批处理任务获取MSBuild输出参数?

时间:2015-12-11 10:26:43

标签: msbuild

我有一个MSBuild目标,它在几个项目上运行Exec任务。如何获取每个退出代码?

我可以使用它来获取所有退出代码,并且仅在输入文件自上次运行后发生更改时运行(即增量构建):

<ItemGroup>
    <TestItem Include="MyFile1" />
    <TestItem Include="MyFile2" />
    <TestItem Include="MyFile10" />
</ItemGroup>

<Target Name="PrepareItemTest">
    <ItemGroup>
        <TestItem>
            <!-- The timestamp of the "done file" is used below to detect if this target has been run since the inputs have been modified. -->
            <DoneFilePath>%(TestItem.RelativeDir)%(TestItem.Filename).done/DoneFilePath>
        </TestItem>
    </ItemGroup>
</Target>

<Target Name="ItemTest"
      DependsOnTargets="PrepareItemTest"
      Inputs="@(TestItem);@(OtherInputs)"
      Outputs="%(TestItem.DoneFilePath)">

    <Exec Command="ECHO Running on %(TestItem.Identity) |findstr 1" IgnoreExitCode="true">
        <Output TaskParameter="ExitCode" PropertyName="TestExitCode"/>
    </Exec>

    <Error Condition=" '$(TestExitCode)' != '0' " Text="Error $TestExitCode" />
    <WriteLinesToFile Condition=" '$(TestExitCode)' == '0' " File="%(TestItem.DoneFilePath)" Lines="Ran successfully on %(TestItem.Filename)%(TestItem.Extension)" />
</Target>

输出:

Ran ItemTest. Exit code=0
Ran ItemTest. Exit code=1

因此,这会打印返回的所有不同退出代码,但它不会将它们与输入项相关联,因此我不知道哪些输入已成功处理,哪些输入未成功处理。

1 个答案:

答案 0 :(得分:2)

实现此目的的最简单方法是batch而非目标而不是任务本身。这实际上有效地将循环从(伪代码)移动到了一个级别:

target PrepareItemTest {
    foreach item in TestItem {
        TestExitCode.append(exec().result))
    }
    warn("exit codes: " + TestExitCode)
}

target PrepareItemTest {
    foreach item in TestItem {
        TestExitCode.append(exec().result))
        warn("exit code: " item + " " + TestExitCode)
    }
}

如果项目代表生成输出的文件,则这很简单,您应该在Inputs属性中进行批处理(并定义Outputs以获得正确的增量行为)。

对于您给出的示例,它有点令人困惑,因为目标不会产生一组输出文件。这意味着您必须滥用目标的Outputs属性才能获得批处理行为。你可以这样做:

<Target Name="ItemTest" Outputs="%(TestItem.Identity)">
    <Exec Command="ECHO Running on @(TestItem->'%(Identity)') |findstr 1" IgnoreExitCode="true">
        <Output TaskParameter="ExitCode" PropertyName="TestExitCode"/>
    </Exec>

    <Warning Text="Ran ItemTest for @(TestItem). Exit code=$(TestExitCode)" />
</Target>

哪个产生

Project "D:\work\batch-over-target.proj" on node 1 (default targets).
ItemTest:
  ECHO Running on MyItem1 |findstr 1
  Running on MyItem1
D:\work\batch-over-target.proj(14,5): warning : Ran ItemTest for MyItem1. Exit code=0
ItemTest:
  ECHO Running on MyItem2 |findstr 1
  The command "ECHO Running on MyItem2 |findstr 1" exited with code 1.
D:\work\batch-over-target.proj(14,5): warning : Ran ItemTest for MyItem2. Exit code=1
ItemTest:
  ECHO Running on MyItem10 |findstr 1
  Running on MyItem10
D:\work\batch-over-target.proj(14,5): warning : Ran ItemTest for MyItem10. Exit code=0
Done Building Project "D:\work\batch-over-target.proj" (default targets).

这样做的原因是,在批处理中,使用@(ItemName)访问的项目仅包含适合批处理的结果。如果您小心确保每个批次只有一个项目,则可以将输出与输入相关联。