2008-09-16 71 views
5

任何人都知道任何可以執行PowerShell腳本並傳遞不同參數的好的MSBuild任務嗎?任何好的PowerShell MSBuild任務?

我能找到B# .NET Blog: Invoking PowerShell scripts from MSBuild,但我希望有些更精美的東西。

如果我找不到任何東西,我當然會繼續前進,並使用該博客作爲首發來打磨自己。

+0

我會使用博客文章作爲首發。我們正在與微軟的顧問合作,這是他向我們推薦的帖子。我嘗試了codeplex上的Powershell MSBuild任務,並且它在Bart De Smet創作的任務中工作的Powershell腳本中出錯。 – 2010-01-22 14:11:14

回答

7

您可能還想看看Psake - 基於PowerShell的構建環境。

9
4

Duplicate Question and Answer I Posted,這裏爲後人投票結束的時候。關鍵的區別是,這個問題被限制爲OOTB並且我的自我回答停留在該限制內。

問題

PowerShell的似乎並不有一個簡單的方法用在正確與不PowerShell的呼叫者互操作的方式任意命令,然後泡瞭解析和執行錯誤觸發它 - 例如,cmd.exeTeamCity

我的問題很簡單。對於我來說,使用OOTB MSBuild v4和PowerShell v3(開放建議)的最佳方式是不排除適合生產的MSBuild任務,但它需要比建議「這很容易 - 比PowerShell任務工廠樣本更強大」調整它和/或成爲它的維護者/父母「)來運行一個命令(或者是一個小腳本段,或者(最常見的)調用.ps1腳本

我在想它應該是正常的東西:

<Exec 
    IgnoreStandardErrorWarningFormat="true" 
    Command="PowerShell &quot;$(ThingToDo)&quot;" /> 

可悲的是不工作: -

  1. 如果ThingToDo無法解析,它靜靜地失敗
  2. 如果ThingToDo是一個腳本調用不存在的,它失敗
  3. 如果你想傳播的ERRORLEVEL基於.cmd結果,它變得毛茸茸
  4. 如果你想在ThingToDo嵌入"報價,它不會工作

那麼,什麼是運行PowerShell的MSBuild中應該是的防彈呢?有什麼我可以PsGet使一切OK?

回答

Weeeeelll,你可以使用一些長篇大論下去,直到你找到一個更好的辦法: -

<PropertyGroup> 
    <__PsInvokeCommand>powershell "Invoke-Command</__PsInvokeCommand> 
    <__BlockBegin>-ScriptBlock { $errorActionPreference='Stop';</__BlockBegin> 
    <__BlockEnd>; exit $LASTEXITCODE }</__BlockEnd> 
    <_PsCmdStart>$(__PsInvokeCommand) $(__BlockBegin)</_PsCmdStart> 
    <_PsCmdEnd>$(__BlockEnd)"</_PsCmdEnd> 
</PropertyGroup> 

然後是 '所有',你需要做的是:

<Exec 
    IgnoreStandardErrorWarningFormat="true" 
    Command="$(_PsCmdStart)$(ThingToDo)$(_PsCmdEnd)" /> 

這個(除了捕獲所有我能想到的錯誤類型之外)的單一救贖功能是它可以在任何PowerShell版本和任何MSBuild版本上運行OOTB。

我會穿上我的大衣。

0

有了一點樂趣,我設法想出使這項工作的一個相當乾淨的方式:

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <!-- #1 Place this line at the top of any msbuild script (ie, csproj, etc) --> 
    <PropertyGroup><PowerShell># 2>nul || type %~df0|find /v "setlocal"|find /v "errorlevel"|powershell.exe -noninteractive -&amp; exit %errorlevel% || #</PowerShell></PropertyGroup> 

    <!-- #2 in any target you want to run a script --> 
    <Target Name="default" > 

    <PropertyGroup> <!-- #3 prefix your powershell script with the $(PowerShell) variable, then code as normal! --> 
     <myscript>$(PowerShell) 
     # 
     # powershell script can do whatever you need. 
     # 
     dir ".\*.cs" -recurse |% { 
     write-host Examining file named: $_.FullName 
     # do other stuff here... 
     } 
     $answer = 2+5 
     write-host Answer is $answer ! 
     </myscript> 
    </PropertyGroup> 

    <!-- #4 and execute the script like this --> 
    <Exec Command="$(myscript)" EchoOff="true" /> 
    </Target> 
</Project> 

注:

  • 您仍然可以使用標準的Exec的任務功能! (參見:https://msdn.microsoft.com/en-us/library/x8zx72cd.aspx
  • ,如果你的PowerShell腳本需要使用<>或&字符,只需將內容放在CDATA包裝:

    <script2><![CDATA[ $(PowerShell) 
        # your powershell code goes here! 
        write-host "<<Hi mom!>>" 
    ]]></script2> 
    
  • ,如果你想返回的項目到的MSBuild腳本,您可以讓他們:

    <script3>$(PowerShell) 
        # your powershell code goes here! 
        (dir "*.cs" -recurse).FullName 
    </script3> 
    
    <Exec Command="$(script3)" EchoOff="true" ConsoleToMSBuild="true"> 
        <Output TaskParameter="ConsoleOutput" PropertyName="items" /> 
    </Exec> 
    <Touch Files="$(items)" /> 
    

見!那麼你可以使用這些項目與另一個msbuild任務:D