如何在不生成msbuild.exe进程的情况下从Powershell运行MSBuild?

时间:2009-01-23 06:07:21

标签: .net powershell msbuild

我正在考虑通过直接点击MSBuild程序集从Powershell脚本运行MSBuild(而不是查找MSBuild安装路径并启动msbuild.exe作为子进程)。

有人这样做过吗?运行构建的最简单,最直接的方法是什么?你想指出哪种技术都有利弊吗? (我对在与脚本的其余部分相同的进程/ appdomain中运行msbuild可能引起的任何问题特别感兴趣。)

目前我的想法是这样的:

[void][System.Reflection.Assembly]::Load('Microsoft.Build.Engine, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][Microsoft.Build.BuildEngine.Engine]::GlobalEngine.BuildProjectFile("path/main.proj")

5 个答案:

答案 0 :(得分:14)

工作和生成输出的最简单的嵌入式构建调用是:

[void][System.Reflection.Assembly]::Load('Microsoft.Build.Engine, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
$engine = New-Object Microsoft.Build.BuildEngine.Engine
$engine.RegisterLogger((New-Object Microsoft.Build.BuildEngine.ConsoleLogger))
$engine.BuildProjectFile('fullPath\some.proj')

然而,事实证明直接在Powershell(V1)中嵌入MSBuild是有问题的:

'MSBUILD : warning MSB4056: The MSBuild engine must be called on
a single-threaded-apartment. Current threading model is "MTA".
Proceeding, but some tasks may not function correctly.'

为什么我们为什么在管理环境中工作时仍然在2009年支付COM税?

我的结论是在Powershell(V1)中嵌入MSBuild并不是一个好主意。作为参考,我还包括我最终使用的基于流程的方法:

[void][System.Reflection.Assembly]::Load('Microsoft.Build.Utilities.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
$msbuild = [Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToDotNetFrameworkFile("msbuild.exe", "VersionLatest")
&$msbuild fullPath\some.proj

答案 1 :(得分:5)

我非常强烈建议查看PSake

让我引用该页面的一部分:

  

请记住,psake是围绕PowerShell的语法糖。所以你可以在PowerShell中做任何事情,你可以用psake做。这意味着您可以运行MSBuild,NAnt或其他脚本。无需完全替换当前的构建系统。您可以使用psake自动化和扩展它!

     

psake会自动将适当版本的.NET Framework添加到其路径中。因此,您可以访问MSBuild,csc.exe,vbc.exe或$ env:windir \ Microsoft.NET \ Framework \ $ version \中安装的任何其他工具,而不使用完全限定的路径。

答案 2 :(得分:3)

另一种可能更有用的方法是创建一个msbuild cmdlet。 MsBuild有一个很好的API,有很多关于如何从C#/ VB等编译语言中使用它的示例。构建一个可以为powershell脚本提供更好语法的cmdlet非常容易。

答案 3 :(得分:3)

我一直在寻找同样的事情。在JaredPar的带领下,我找到了以下内容:

这是制作cmdlet的方法。

http://bartdesmet.net/blogs/bart/archive/2008/02/03/easy-windows-powershell-cmdlet-development-and-debugging.aspx

MSBuild API是这些命名空间的一部分:

Microsoft.Build.Framework

Microsoft.Build.BuildEngine

可以在这里找到MSBuild文档(这完整性比回答您的问题更多):

http://msdn.microsoft.com/en-us/library/wea2sca5.aspx

答案 4 :(得分:0)

曾几何时我一直在玩增强的MSBuild构建过程(比如,更积极地跳过构建的某些部分)。

有两种选择:

  1. 通过加载DLL来在您自己的进程中托管MSBuild。
  2. 以常规方式生成MSBuild.exe然后注入它(例如记录器提供了一个不错的方式)。
  3. 我已经实现了两者并且不得不放弃#1,因为它不够灵活。

    例如,MSBuild在其.config文件中有大量的程序集绑定重定向。

    同时托管MSBuild及其API的Visual Studio进程(devenv.exe)最终将这些进程复制到其devenv.exe.config中。我的.exe.config也必须拥有这些,但它会将您绑定到特定的MSBuild版本。当然,您必须修改配置。实际上这不是PS的选项,所以我怀疑你是否能得到一个非常稳定的解决方案。