检查MSBuild任务中是否存在目标

时间:2014-08-20 14:24:02

标签: msbuild msbuild-4.0

这是我的代码:

    <MSBuild Projects="outs.proj" Targets="Build;MyCustomTarget">
</MSBuild>

我需要在执行之前检查outs.proj中是否存在MyCustomTarget。

在未导入MyCustomTarget时抛出错误,因此根据结果使用Build或Build + MyCustomTarget。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

获取目标列表非常麻烦,您可以reflect on TaskHost via BuildEngine获取当前Project或使用内联任务重新评估项目。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="Targets" TaskFactory="CodeTaskFactory" AssemblyName="Microsoft.Build.Tasks.v12.0">
    <ParameterGroup>
      <Project ParameterType="System.String" Required="true" />
      <All ParameterType="System.String[]" Output="true" />
      <Run ParameterType="System.String[]" Output="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="Microsoft.Build" />
      <Reference Include="System.Xml" />
      <Code>
        All = new Microsoft.Build.Evaluation.Project(Project).Targets.Select(t => t.Key).ToArray();
        Run = Run.Where(All.Contains).ToArray();
      </Code>
    </Task>
  </UsingTask>

  <Target Name="Foo">
    <Targets Project="$(MSBuildProjectFullPath)" Run="Foo;Baz">
      <Output TaskParameter="All" ItemName="All" />
      <Output TaskParameter="Run" ItemName="Run" />
    </Targets>
    <Message Text="All Targets: @(All)" />
    <Message Text="Run Targets: @(Run)" />
  </Target>

  <Target Name="Bar" />
</Project>

编辑:

您没有提供太多详细信息,因此我无法解决您的具体问题,但如果new Project(Project)投掷可能会尝试ProjectCollection.GlobalProjectCollection.LoadProject(Project)而不是Targets;同一个集合包含LoadedProjects属性以及GetLoadedProjectsUnloadProject方法,可以绕过您的异常。如果您控制项目文件并且它没有Import,那么您可能希望尝试将其解析为简单的XML文件而不是完全成熟的MSBuild项目。

<XmlPeek XmlInputPath="$(MSBuildProjectFullPath)" Query="/p:Project/p:Target/@Name" Namespaces="&lt;Namespace Prefix='p' Uri='http://schemas.microsoft.com/developer/msbuild/2003' /&gt;">
  <Output TaskParameter="Result" ItemName="All" />
</XmlPeek>
<ItemGroup>
  <In Include="Foo;Baz" />
  <Out Include="@(In)" Exclude="@(All)" />
  <Run Include="@(In)" Exclude="@(Out)" />
</ItemGroup>
<Message Text"@(Run)" />

在任何一种情况下,您都会将outs.proj路径传递给您选择的任何方法,然后使用该项目中的所有目标(@(All))返回Foo;Bar,然后您过滤目标从Foo;Baz下降到Foo,因为Baz未在@(All)中退出。然后,您可以使用此信息执行任何操作,例如: <MSBuild Projects="outs.proj" Targets="Build;@(Run)">