Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call MSBuild from C#

Tags:

c#

.net

msbuild

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

like image 813
David Schmitt Avatar asked Feb 11 '09 12:02

David Schmitt


People also ask

Can I use MSBuild without Visual Studio?

NET Framework 3.5 or later. MSBuild provides an easy way to build a release from the command line on a machine on which Visual Studio is not installed. The only components you must have installed on the machine are the . NET Framework and the InstallShield Standalone Build.

How do I run MSBuild target?

To build a specific target of a specific project in a solution. At the command line, type MSBuild.exe <SolutionName>. sln , where <SolutionName> corresponds to the file name of the solution that contains the target that you want to execute.

What is the Path to MSBuild?

For example, the path to MSBuild.exe installed with Visual Studio 2019 Community is C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe You can also use the following PowerShell module to locate MSBuild: vssetup.


3 Answers

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.

like image 193
Peter Avatar answered Sep 24 '22 02:09

Peter


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();
}
like image 40
Philippe Monnet Avatar answered Sep 24 '22 02:09

Philippe Monnet


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) });
    }

}
like image 1
crimbo Avatar answered Sep 22 '22 02:09

crimbo