32

How do I build a C# solution programmatically?

I should be able to pass the path of a solution and get the output messages (or just build the solution). How do I achieve this in C#?

I need this because we are building a single solution for our projects when it now gets everything from SVN and also builds it. Next would be deploying it all in one click.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • @Nix: I think the OP means "compile code at runtime"? – Ry- Jun 28 '11 at 18:35
  • possible duplicate of [How to programmatically build a visual studio solution ?](http://stackoverflow.com/questions/1713075/how-to-programmatically-build-a-visual-studio-solution) – Bertrand Marron Jun 28 '11 at 18:43

7 Answers7

29

See .NET 4.0 MSBuild API introduction for an example using the .NET 4.0 MSBuild API:

List<ILogger> loggers = new List<ILogger>();
loggers.Add(new ConsoleLogger());
var projectCollection = new ProjectCollection();
projectCollection.RegisterLoggers(loggers);
var project = projectCollection.LoadProject(buildFileUri); // Needs a reference to System.Xml
try
{
    project.Build();
}
finally
{
    projectCollection.UnregisterAllLoggers();
}

A simpler example:

var project = new Project(buildFileUri, null, "4.0");
var ok = project.Build(); // Or project.Build(targets, loggers)
return ok;

Remember to use the .NET 4 Profile (not the Client profile).

Add the following references: System.XML, Microsoft.Build, Microsoft.Build.Framework, and optionally Microsoft.Build.Utilities.v4.0.

Also look at Stack Overflow question Running MSBuild programmatically.

To build a solution, do the following:

var props = new Dictionary<string, string>();
props["Configuration"] = "Release";
var request = new BuildRequestData(buildFileUri, props, null, new string[] { "Build" }, null);
var parms = new BuildParameters();
// parms.Loggers = ...;

var result = BuildManager.DefaultBuildManager.Build(parms, request);
return result.OverallResult == BuildResultCode.Success;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
W1M0R
  • 3,367
  • 3
  • 30
  • 32
23

Most of the answers are providing ways to do it by calling external commands, but there is an API, Microsoft.Build.Framework, to build via C#.


Code from blog post:

using Microsoft.Build.BuildEngine;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

public class SolutionBuilder
{
    BasicFileLogger b;
    public SolutionBuilder() { }

    [STAThread]
    public string Compile(string solution_name,string logfile)
    {
        b = new BasicFileLogger();
        b.Parameters = logfile;
        b.register();
        Microsoft.Build.BuildEngine.Engine.GlobalEngine.BuildEnabled = true;
        Project p = new Project (Microsoft.Build.BuildEngine.Engine.GlobalEngine);
        p.BuildEnabled = true;
        p.Load(solution_name);
        p.Build();
        string output = b.getLogoutput();
        output += “nt” + b.Warningcount + ” Warnings. “;
        output += “nt” + b.Errorcount + ” Errors. “;
        b.Shutdown();
        return output;
    }
}
// The above class is used and compilation is initiated by the following code,
static void Main(string[] args)
{
    SolutionBuilder builder = new SolutionBuilder();
    string output = builder.Compile(@”G:CodesTestingTesting2web1.sln”, @”G:CodesTestingTesting2build_log.txt”);
    Console.WriteLine(output);
    Console.ReadKey();
}

Note the code in that blog post works, but it is a little dated. The

Microsoft.Build.BuildEngine

has been broken up into some pieces.

Microsoft.Build.Construction

Microsoft.Build.Evaluation

Microsoft.Build.Execution

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nix
  • 57,072
  • 29
  • 149
  • 198
  • 2
    looks like "Automated compilation of Visual Studio Projects through C# using MSBuild" link is broken –  Dec 19 '12 at 23:18
  • 4
    This info is outdated - if you use the Engine class, you'll get this warning: "This class has been deprecated. Please use Microsoft.Build.Evaluation.ProjectCollection from the Microsoft.Build assembly instead.". So the answer below using Project and ProjectCollection is the right answer. – crimbo Jul 23 '14 at 19:30
  • The link is (effectively) broken. It redirects to a generic page, *".NET API Browser"*. – Peter Mortensen Jan 03 '20 at 12:36
  • What blog post is referred to? What is its link? (Respond by [editing your answer](https://stackoverflow.com/posts/6511466/edit), not here in comments (as appropriate).) – Peter Mortensen Jan 03 '20 at 12:37
5
// Fix to the path of your MSBuild executable
var pathToMsBuild = "C:\\Windows\\DotNet\\Framework\\msbuild.exe";

Process.Start(pathToMsBuild + " " + pathToSolution);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
2

You can try blog post Take control of MSBuild using MSBuild API.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ram
  • 15,908
  • 4
  • 48
  • 41
2

You can create a .proj file:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <!-- Common -->
    <Solution Include="Common\Util\Util.sln"/>
    <Solution Include="Common\EventScheduler\EventSchedulerSolution\EventSchedulerSolution.sln"/>
    <!-- Server -->
    <Solution Include="Server\DataLayer\DataTransferObjects\SharedModel\SharedModel.sln"/>
    <Solution Include="Server\DataLayer\DataTier\ESPDAL.sln"/>
    <!-- Internal Tools -->
    <Solution Include="InternalTools\ServerSchemaUtility\ServerSchemaUtility.sln"/>
  </ItemGroup>
  <Target Name="Rebuild">
    <MSBuild Projects="@(Solution)" Targets="Rebuild" Properties="Configuration=Release"/>
  </Target>
</Project>

And then call msbuild.exe using the project file as an argument. Below is a batch file example. From C#, you could call Process.Start as indicated by other posters.

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" BuildSolutions.proj

pause
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jon Raynor
  • 3,804
  • 6
  • 29
  • 43
1

If you need to trigger the build from Visual Studio extension code, you must consider the limitations imposed by IVsBuildManagerAccessor interface - see the General Notes, including new IVsBuildManagerAccessor.docx from Managed Package Framework for Projects. Its fork is also available at GitHub.

In Visual Studio 2010 with MSBuild 4.0, there are new interactions between the Solution Build Manager and MSBuild which impact project systems utilizing these services. MSBuild 4.0 contains a new component called the Build Manager (not to be confused with the Solution Build Manager which is a VS component) which controls the submission of build requests. This became necessary as Visual Studio 2010 now allows parallel builds to occur (notably native projects) and access to shared resources such as the CPU needed to be mediated. For project systems which previously simply called Project.Build() to invoke a build several changes must be made. The project system now must:

  1. Ask for the SVsBuildManagerAccessor service using the IServiceProvider interface. This should be done soon after the project system is loaded, well before any builds might occur.
  2. Notify the system if you need the UI thread
  3. Notify the system if you are doing a design-time build.
  4. Register its loggers using the Build Manager Accessor.
  5. Submit build requests directly to the MSBuild Build Manager, rather than invoking a method on the Project.
Community
  • 1
  • 1
0

Surely you can use MSBuild to build any Visual Studio solution file.

I believe you can use Process.Start to invoke MSBuild with appropriate parameters.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Davide Piras
  • 43,984
  • 10
  • 98
  • 147