Reputation: 919
Here is my code:
<MSBuild Projects="outs.proj" Targets="Build;MyCustomTarget">
</MSBuild>
I need to check if MyCustomTarget exists in outs.proj before executing.
It throws an error when MyCustomTarget is not imported, so depending on the result use either Build or Build+MyCustomTarget.
Thanks in advance for your help.
Upvotes: 0
Views: 2022
Reputation: 10432
Getting a list of targets is cumbersome, you can either reflect on TaskHost
via BuildEngine
to get current Project
or re-evaluate the project with an inline task.
<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>
Edit:
You don't provide much details so I can't help with your particular issue, but if new Project(Project)
throws may be try ProjectCollection.GlobalProjectCollection.LoadProject(Project)
instead to get to the Targets
; the same collection has the LoadedProjects
property as well as GetLoadedProjects
and UnloadProject
methods to play around with to get around your exception. If you're in control of the project file and it's flat with no Import
you might want to try parsing it as a simple XML file rather than a fully fledged MSBuild project.
<XmlPeek XmlInputPath="$(MSBuildProjectFullPath)" Query="/p:Project/p:Target/@Name" Namespaces="<Namespace Prefix='p' Uri='http://schemas.microsoft.com/developer/msbuild/2003' />">
<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)" />
In either case, you pass outs.proj
path to whichever method you choose go with and get back @(All)
with all of the targets in that project (Foo;Bar
) then you filter your targets down from Foo;Baz
to just Foo
since Baz
doesn't exit in @(All)
. Then you do whatever you want to do with this information, e.g. <MSBuild Projects="outs.proj" Targets="Build;@(Run)">
.
Upvotes: 1