2009-01-23 47 views
10

我正在考虑通过直接点击MSBuild程序集(而不是查找MSBuild安装路径并启动msbuild.exe作为子进程)从Powershell脚本运行MSBuild。如何从Powershell运行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") 

回答

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.' 

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

我的结论是,在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 
3

不同的和潜在的更实用的方法是做一个MSBuild cmdlet的。 MsBuild有一个很好的API,并且有很多关于如何使用C#/ VB等编译语言的示例。构建一个cmdlet将会非常简单,它将为您的PowerShell脚本提供更好的语法。

+3

那么这是我的问题 - 你有任何链接到“关于如何使用它的许多样本”或提供你自己的? – 2009-01-23 14:06:20

5

我会非常建议看看PSake

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

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

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

+2

请不要进入'msbuild sucks,使用基于powershell的构建来代替'的哲学辩论,因为那不是我的问题,真的。 – 2009-01-23 14:54:42

+0

你在说什么哲学辩论?你读过这个页面吗?它提供了一个简单的方法来包装MSBuild。 – EBGreen 2009-01-23 15:01:29

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

0

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

有两种选择:

  1. 主机的MSBuild在自己的过程加载其DLL文件。
  2. 产生MSBuild.exe的常规方式,然后注入(例如记录器提供了一个体面的方式)。

我已经实施了这两个方案,因为它不够灵活而不得不放弃#1。

例如,MSBuild在其.config文件中加载了程序集绑定重定向。

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

相关问题