简体   繁体   中英

How to call MSBuild from C#

Is there a better way to call MSBuild from C#/.NET than shelling out to the msbuild.exe? If yes, how?

Yes, add a reference to Microsoft.Build.Engine and use the Engine class.

PS: Take care to reference the right version. There are 2.0 and 3.5 assemblies and you'll have to make sure that everyone gets the right one .

For a .NET 2.0-specific version, you can use the following:

Engine engine = new Engine();
engine.BinPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.System)
    + @"\..\Microsoft.NET\Framework\v2.0.50727";

FileLogger logger = new FileLogger();
logger.Parameters = @"logfile=C:\temp\test.msbuild.log";
engine.RegisterLogger(logger);

string[] tasks = new string[] { "MyTask" };
BuildPropertyGroup props = new BuildPropertyGroup();
props.SetProperty("parm1","hello Build!");

try
{
  // Call task MyTask with the parm1 property set
  bool success = engine.BuildProjectFile(@"C:\temp\test.msbuild",tasks,props);
}
catch (Exception ex)
{
  // your error handler
}
finally
{
 engine.UnregisterAllLoggers();
 engine.UnloadAllProjects();
}

If you use Microsoft.Build.Engine.Engine , you'll get a warning: This class has been deprecated. Please use Microsoft.Build.Evaluation.ProjectCollection from the Microsoft.Build assembly instead. This class has been deprecated. Please use Microsoft.Build.Evaluation.ProjectCollection from the Microsoft.Build assembly instead.

Now, the proper way to run MSBuild from C# looks like this:

public sealed class MsBuildRunner
{

    public bool Run(FileInfo msbuildFile, string[] targets = null, IDictionary<string, string> properties = null, LoggerVerbosity loggerVerbosity = LoggerVerbosity.Detailed)
    {
        if (!msbuildFile.Exists) throw new ArgumentException("msbuildFile does not exist");

        if (targets == null)
        {
            targets = new string[] {};
        }
        if (properties == null)
        {
            properties = new Dictionary<string, string>();
        }

        Console.Out.WriteLine("Running {0} targets: {1} properties: {2}, cwd: {3}",
                              msbuildFile.FullName,
                              string.Join(",", targets),
                              string.Join(",", properties),
                              Environment.CurrentDirectory);
        var project = new Project(msbuildFile.FullName, properties, "4.0");
        return project.Build(targets, new ILogger[] { new ConsoleLogger(loggerVerbosity) });
    }

}

If all you want is the path to the MSBuild tools folder, you can use the ToolLocationHelper class from the Microsoft.Build.Utilities.Core assembly:

var toolsetVersion = ToolLocationHelper.CurrentToolsVersion;
var msbuildDir = ToolLocationHelper.GetPathToBuildTools(toolsetVersion);

CurrentToolsVersion在ToolLocationHelper类中不可用,我在这里使用V.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM