Given a build file (.csproj or msbuild.xml or whatever), I'd like to run a msbuild command that lists all the available, defined targets.
Does that function exist?
I know I could do an Xpath search or something, on the build file, but that wouldn't find targets that a开发者_开发问答re defined in included files.
Using MSBuild 2.0/3.5 : Custom Task
You could write a custom msbuild task like this :
using System;
using System.Collections.Generic;
using Microsoft.Build.BuildEngine;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace MSBuildTasks
{
public class GetAllTargets : Task
{
[Required]
public String ProjectFile { get; set; }
[Output]
public ITaskItem[] Targets { get; set; }
public override bool Execute()
{
var project = new Project(BuildEngine as Engine);
project.Load(ProjectFile);
var taskItems = new List<ITaskItem>(project.Targets.Count);
foreach (Target target in project.Targets)
{
var metadata = new Dictionary<string, string>
{
{"Condition", target.Condition},
{"Inputs", target.Inputs},
{"Outputs", target.Outputs},
{"DependsOnTargets", target.DependsOnTargets}
};
taskItems.Add(new TaskItem(target.Name, metadata));
}
Targets = taskItems.ToArray();
return true;
}
}
}
That you'll use like that:
<Target Name="TestGetAllTargets">
<GetAllTargets ProjectFile="$(MSBuildProjectFile)">
<Output ItemName="TargetItems" TaskParameter="Targets"/>
</GetAllTargets>
<Message Text="Name: %(TargetItems.Identity) Input: %(TargetItems.Input) --> Output: %(TargetItems.Output)"/>
</Target>
Using MSBuild 4.0 : Inline task
With MSBuild 4 you could use the new shiny thing : the inline task. Inline task allows you to define the behavior directly in msbuild file.
<UsingTask TaskName="GetAllTargets"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
<ParameterGroup>
<ProjectFile ParameterType="System.String" Required="true"/>
<TargetsOut ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true"/>
</ParameterGroup>
<Task>
<Reference Include="System.Xml"/>
<Reference Include="Microsoft.Build"/>
<Reference Include="Microsoft.Build.Framework"/>
<Using Namespace="Microsoft.Build.Evaluation"/>
<Using Namespace="Microsoft.Build.Execution"/>
<Using Namespace="Microsoft.Build.Utilities"/>
<Using Namespace="Microsoft.Build.Framework"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
var project = new Project(ProjectFile);
var taskItems = new List<ITaskItem>(project.Targets.Count);
foreach (KeyValuePair<string, ProjectTargetInstance> kvp in project.Targets)
{
var target = kvp.Value;
var metadata = new Dictionary<string, string>
{
{"Condition", target.Condition},
{"Inputs", target.Inputs},
{"Outputs", target.Outputs},
{"DependsOnTargets", target.DependsOnTargets}
};
taskItems.Add(new TaskItem(kvp.Key, metadata));
}
TargetsOut = taskItems.ToArray();
]]>
</Code>
</Task>
</UsingTask>
<Target Name="Test">
<GetAllTargets ProjectFile="$(MSBuildProjectFile)">
<Output ItemName="TargetItems" TaskParameter="TargetsOut"/>
</GetAllTargets>
<Message Text="%(TargetItems.Identity)"/>
</Target>
Starting with Visual Studio 16.6 preview 1, this is implemented in MSBuild.
Example usage:
msbuild myProject.proj -targets
This should go out with Visual Studio 16.6 preview 1 (at some point in the future).
(source: https://github.com/microsoft/msbuild/pull/5032#issuecomment-587901124)
Documentation:
-targets[:file]
Prints a list of available targets without executing the
actual build process. By default the output is written to
the console window. If the path to an output file
is provided that will be used instead.
(Short form: -ts)
Example:
-ts:out.txt
Update for Dotnet Core 6
dotnet "C:\Program Files\dotnet\sdk\6.0.300\MSBuild.dll" HelloWorld.csproj -targets
or
dotnet msbuild HelloWorld.csproj -targets
精彩评论