以编程方式构建msbuild 15项目
我正在尝试构建一个使用VS2017创建的简单C#7类库项目。
框架程序集中的MSBuild已过时,因此我在C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
MSBuild文件夹中引用Microsoft.Build
, Microsoft.Build.Engine
和Microsoft.Build.Framework
( C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
)。
当我这样做时:
using (var collection = new ProjectCollection()) { var proj = collection.LoadProject(@"c:\projects\Sample\Sample.csproj"); // <-- exception proj.Build(new[] {new ConsoleLogger()}); }
我收到了InvalidProjectFileException: The tools version "15.0" is unrecognized. Available tools versions are "4.0", "2.0".
InvalidProjectFileException: The tools version "15.0" is unrecognized. Available tools versions are "4.0", "2.0".
是否有使用最新构建工具和C#7编译器调用构建的编程方法?
我对我的团队有类似的需求,我为C#编写了一个Builder库,支持多个版本的Visual Studio。 我无法使Project.Buildfunction正常工作,所以我直接执行了MsBuild.exe。
我是如何建造它的:
使用NuGet的 Microsoft.Build.Framework
使用名为Build的1个目标创建一个新的Project对象
定义正确的ToolsVersion
根据Visual Studio版本的项目:
- 2010年,2012年=> 4.0
- 2013 => 12.0
- 2015 => 14.0
- 2017 => 15.0
添加MsBuild类型的新任务
使用Projects属性包含我需要构建的所有项目
定义ToolsVersion
MsBuild任务的值与项目的值相同
将项目序列化为临时文件
根据ToolsVersion找到正确的MsBuild.exe
4.0,12.0,14.0
在注册表中找到:
Registry.LocalMachine.OpenSubKey($@"SOFTWARE\Microsoft\MSBuild\ToolsVersions\{msBuildVersion}")
15.0
在注册表中不再需要使用Nuget包Microsoft.VisualStudio.Setup.Configuration.Interop
var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); var helper = (ISetupHelper)query; int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance = instances[0]; var instance2 = (ISetupInstance2)instance; var state = instance2.GetState(); // Skip non-complete instance, I guess? // Skip non-local instance, I guess? // Skip unregistered products? if (state != InstanceState.Complete || (state & InstanceState.Local) != InstanceState.Local || (state & InstanceState.Registered) != InstanceState.Registered) { continue; } var msBuildComponent = instance2.GetPackages() .FirstOrDefault( p => p.GetId() .Equals("Microsoft.Component.MSBuild", StringComparison.InvariantCultureIgnoreCase)); if (msBuildComponent == null) { continue; } var instanceRootDirectory = instance2.GetInstallationPath(); var msbuildPathInInstance = Path.Combine(instanceRootDirectory, "MSBuild", msBuildVersion, "Bin", "msbuild.exe"); if (File.Exists(msbuildPathInInstance)) { return msbuildPathInInstance; } } } while (fetched > 0);
执行MsBuild.exe
使用自定义XML Logger构建序列化项目 – 您可以使用MsBuildExtensionPack提供的项目
阅读结果摘要
从Xml反序列化结果摘要并使用它来确定构建是否失败,发生了哪些错误和警告等。
如果您只需要最新MSBuild.exe的路径,请使用Nuget的Microsoft.Build.Utilities.Core并使用以下代码:
ToolLocationHelper.GetPathToBuildToolsFile("msbuild.exe", ToolLocationHelper.CurrentToolsVersion);
无论是安装Build Tools还是完整的Visual Studio安装,这都有效。
我在项目中遇到了完全相同的问题。
在我的情况下,我想以编程方式构建一个SSDT项目,但我也尝试了其他项目类型。
有趣的是,它在VS2017的构建26228.04(这是Release版本)中运行得非常好,并且在构建版本26228.09中停止工作。
昨天发布的26228.10已经发布,所以我决定再给它一次。
令人惊讶的是,以下对我有用:
- 使用Visual Studio Installer更新到最新的VS2017版本26228.10。
-
我从来没有能够获得
collection.LoadProject(...)
工作而不会得到一些奇怪的错误,但你可以使用此代码来进行构建:BuildResult result = null; using (var pc = new ProjectCollection()) result = BuildManager.DefaultBuildManager.Build( new BuildParameters(pc) { Loggers = new[] { new ConsoleLogger() } }, // Change this path to your .sln file instead of the .csproj. // (It won't work with the .csproj.) new BuildRequestData(@"c:\projects\Sample.sln", // Change the parameters as you need them, // eg if you want to just Build the Debug (not Rebuild the Release). new Dictionary
{ { "Configuration", "Release" }, { "Platform", "Any CPU" } }, null, new[] { "Rebuild" }, null)); if (result.OverallResult == BuildResultCode.Failure) // Something bad happened... -
确保已将所有MSBuild程序集绑定重定向复制到
.config
文件。
如果您还没有这样做,请打开文件C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe.config
并将整个
元素复制到以编程方式使用MSBuild的项目中您自己的.config
文件的
元素。
如果您不重定向MSBuild程序集版本,您将从MSBuild获得一些非常奇怪的错误消息,这些消息将根据您的MSBuild版本而有所不同。
但它肯定会说:如果没有assembly绑定重定向,它绝对不会起作用。 -
如果要构建SSDT项目,还需要执行一个步骤:
更改.sqlproj
文件中的以下两行11.0 11.0 至
15.0 15.0
我不是100%肯定为什么,但这些步骤对我来说非常合适!
但是因为MSBuild在编程上有点“难”(在我看来它有时和天气预报一样稳定),所以我的方法很可能不适用于你的情况。
这已在msbuild的PreRelease版本( 15.5.0-preview-000072-0942130 )中解决,请参阅MsBuild问题#2369:msbuild nuget包无法打开vs2017 csproj文件 。 因此,将来不再需要进一步的黑客攻击