如何在C#中以编程方式构建解决方案?

32

如何以程序化方式构建C#解决方案?

我应该能够传递解决方案的路径并获取输出消息(或仅构建解决方案)。在C#中如何实现这一点?

我需要这样做是因为我们正在为项目构建单个解决方案,当它从SVN获取所有内容并进行构建时。下一步将是一键部署所有内容。


@Nix:我认为OP的意思是“在运行时编译代码”? - Ry-
可能是重复的问题:如何以编程方式构建Visual Studio解决方案? - Bertrand Marron
7个回答

30

查看.NET 4.0 MSBuild API入门,以获取使用.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();
}

一个更简单的例子:

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

记得使用 .NET 4档案(而不是 客户端档案)。

添加以下引用:System.XML、Microsoft.Build、Microsoft.Build.Framework,以及可选的 Microsoft.Build.Utilities.v4.0。

还要查看 Stack Overflow 的问题 Running MSBuild programmatically

要构建解决方案,请执行以下操作:

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;

23

大多数答案都提供了通过调用外部命令进行构建的方法,但是确实有一个API Microsoft.Build.Framework可以通过C#进行构建。


博客文章中的代码:

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

请注意,该博客文章中的代码可行,但有点过时。

Microsoft.Build.BuildEngine

已经被拆分成一些部分。

Microsoft.Build.Construction

Microsoft.Build.Evaluation

Microsoft.Build.Execution


2
似乎“使用MSBuild通过C#自动编译Visual Studio项目”的链接已经失效。 - user677607
4
此信息已过时 - 如果您使用Engine类,将会收到以下警告:“此类已被弃用。请改用来自Microsoft.Build程序集的Microsoft.Build.Evaluation.ProjectCollection。” 因此,下面使用Project和ProjectCollection的答案是正确的。 - crimbo
链接(实际上)已经失效。它重定向到一个通用页面,“.NET API浏览器” - Peter Mortensen
所指的博客文章是哪篇?它的链接是什么?(请通过编辑您的答案进行回复,而不是在评论中回复(如果适用)。) - Peter Mortensen

5
// Fix to the path of your MSBuild executable
var pathToMsBuild = "C:\\Windows\\DotNet\\Framework\\msbuild.exe";

Process.Start(pathToMsBuild + " " + pathToSolution);

2
您可以创建一个.proj文件:
<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>

然后使用项目文件作为参数调用msbuild.exe。以下是一个批处理文件示例。从C#中,您可以像其他帖子中所示那样调用Process.Start。

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

pause

2

1
如果您需要从Visual Studio扩展代码触发构建,则必须考虑IVsBuildManagerAccessor接口所施加的限制-请参见“概述”部分,包括Managed Package Framework for Projects中的新IVsBuildManagerAccessor.docx。其派生版本也可在GitHub上获得。
在使用MSBuild 4.0的Visual Studio 2010中,解决方案构建管理器和MSBuild之间有新的交互,影响使用这些服务的项目系统。MSBuild 4.0包含一个名为Build Manager的新组件(不要与VS组件Solution Build Manager混淆),该组件控制构建请求的提交。这是必需的,因为Visual Studio 2010现在允许并行构建(特别是本地项目),并且需要协调对共享资源(例如CPU)的访问。对于以前只需调用Project.Build()来启动构建的项目系统,必须进行几个更改。现在,项目系统必须:
  1. 使用IServiceProvider接口请求SVsBuildManagerAccessor服务。应在加载项目系统后尽早执行此操作,而不是在任何构建可能发生之前。
  2. 如果需要UI线程,则通知系统。
  3. 如果正在进行设计时构建,则通知系统。
  4. 使用Build Manager Accessor注册其记录器。
  5. 直接向MSBuild Build Manager提交构建请求,而不是调用Project上的方法。

0

你可以使用MSBuild来构建任何Visual Studio解决方案文件。

我相信你可以使用Process.Start来调用带有适当参数的MSBuild。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接