Is there a better way to call MSBuild from C#/.NET than shelling out to the msbuild.exe? If yes, how?
Asked
Active
Viewed 1.3k times
26
-
Related question (but uses Powershell instead of raw C#) - http://stackoverflow.com/questions/472038/how-to-run-msbuild-from-powershell-without-spawning-msbuild-exe-process/473629 – Milan Gardian Mar 08 '12 at 15:13
5 Answers
28
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.

David Schmitt
- 58,259
- 26
- 121
- 165

Peter
- 37,042
- 39
- 142
- 198
16
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();
}

David Schmitt
- 58,259
- 26
- 121
- 165

Philippe Monnet
- 1,152
- 1
- 9
- 13
1
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.
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) });
}
}

crimbo
- 10,308
- 8
- 51
- 55
1
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);

Cameron
- 96,106
- 25
- 196
- 225
-
-
@nainaigu: Make sure you're using the `ToolLocationHelper` from `Microsoft.Build.Utilities.Core` and not the one from `Microsoft.Build.Utilities`. – Cameron Jan 28 '19 at 20:20