2011-04-28 52 views
12

我正在從MSBuild調用PowerShell腳本。 MSBuild能夠捕獲返回的輸出,但認爲該項目已成功構建。PowerShell退出代碼 - 從MSBuild調用

問題是來自PowerShell的退出代碼沒有傳遞給MSBuild中的命令。有人曾經嘗試過,並能夠拋出退出代碼到MSBuild?

testmsbuild.proj

<?xml version="1.0" encoding="utf-8"?> 
<Project DefaultTargets="DesktopBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup> 
    <ScriptLocation>c:\scripts\test.ps1</ScriptLocation> 
    </PropertyGroup> 

    <Target Name="AfterDropBuild" > 
     <Exec Command="powershell.exe -NoProfile -Noninteractive -command &quot;&amp; { $(ScriptLocation)%3Bexit $LASTEXITCODE }&quot; " > 
     <Output TaskParameter="ExitCode" PropertyName="ErrorCode"/> 
     </Exec> 
    </Target>  

</Project> 

test.ps1(當然這是要出錯誤)

function CallFromMSBuild { 

    Invoke-command {Powershell.exe C:\a.ps1} -computername $computers 
} 

當MSBuild項目被觸發時,它應該抓住這個問題,並在構建宜已經失敗(認爲建立成功)

當我從MSBuild打電話

C:\Scripts>msbuild testmsbuild.proj /t:AfterDropBuild 
Microsoft (R) Build Engine Version 4.0.30319.1 
[Microsoft .NET Framework, Version 4.0.30319.225] 
Copyright (C) Microsoft Corporation 2007. All rights reserved. 

Build started 4/28/2011 2:46:29 PM. 
Project "C:\scripts\testmsbuild.proj" on node 1 (AfterDropBuild target(s)). 
AfterDropBuild: 
    powershell.exe -NoProfile -Noninteractive -command "& { c:\scripts\test.ps1;e 
    xit $LASTEXITCODE }" 
    Invoke-Command : Cannot validate argument on parameter 'ComputerName'. The argu 
    ment is null or empty. Supply an argument that is not null or empty and then tr 
    y the command again. 
    At C:\install\test.ps1:3 char:58 
    + Invoke-command {Powershell.exe C:\a.ps1} -computername <<<< $computers 
     + CategoryInfo   : InvalidData: (:) [Invoke-Command], ParameterBind 
    ingValidationException 
     + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power 
    Shell.Commands.InvokeCommandCommand 

Done Building Project "C:\scripts\testmsbuild.proj" (AfterDropBuild target(s)). 


Build succeeded. 
    0 Warning(s) 
    0 Error(s) 

Time Elapsed 00:00:01.04 
+0

相關:http://stackoverflow.com/questions/78069/any-good-powershell-msbuild-tasks – 2012-12-13 21:46:14

回答

4

添加exit $lastexitcode到test.ps1

評論後:

在test.ps1試試這個:

trap {Write-Host -foreground red $_.Exception.Message; exit 1; continue} Invoke-command {Powershell.exe C:\a.ps1} -computername $computers 

基本上,我不認爲是的MSBuild在這裏有毛病。

我試過你的錯誤Invoke-Command並且$lastexitcode被設置爲0,即使Invoke-Command失敗!你可以通過做echo %errorlevel%並看到你得到1來測試它是否有效。從這個cmd本身可以測試。

+0

不幸運!還是一樣。從PowerShell窗口直接運行退出代碼是255 – Sanjeev 2011-04-28 20:35:52

+0

我已經編輯了我的回覆 – manojlds 2011-04-28 20:46:37

+0

感謝您的更新。陷阱{}是訣竅!現在MSbuild說「構建失敗」。問題在於它沒有顯示$ ._ Exception.Message思想。它顯示的是'代碼'C:\ scripts \ testmsbuild.proj(12,3):錯誤MSB3073:使用代碼1'代碼'退出命令「powershell.exe c:\ scripts \ test.ps1」。一半的戰鬥結束了,雖然:) – Sanjeev 2011-04-28 21:07:18

15

這個問題是一個主要搜索引擎的最佳答案。來自James Kovacs的best answer is this(psake的名聲 - 即他在PowerShell和MSBuild集成上有點類似FizzBinned)。

綜上所述,在PS1文件:

  1. 在你的腳本的頂部貼$ErrorActionPreference='Stop'所以它不是默認的,這是SilentlyContinue(在接受答案的trap位有同樣的效果,但更爲間接和混亂)
  2. 棍子在他function exec {...(或使用psake本身)外部的EXE的一個exec { x.exe }
  3. 包裝調用不需要做任何expli CIT exit ...東西

默認的錯誤處理傳播異常起來爲1的ERRORLEVELpowershell.exe myscript.ps1,即在一個MSBuild <Exec你不需要做任何弄虛作假再告訴它忽略退出代碼等。(除非你想做些什麼具體的退出代碼的條件,要在其中做IgnoreExitCode="true"並與<Output元素捕捉到它)

瞭解的最後一個重要的事情是,在PowerShell中,有一個$?這是最後一個表達式的結果(與ErrorAction='Stop'模式無關)隨着每個事情而變化,而$ LastExitCode是系統中觸發的最後一個.exe的'DOS'退出代碼。 Details here - be sure to read the comments

+0

甜!感謝您的信息。我使用博客鏈接中提到的「Exec function」代碼來捕獲來自另一個PS腳本(remoteinvoke.ps1)的錯誤,該腳本從myscript.ps1中調用遠程計算機。陷阱在這些情況下不起作用。我會寫一篇關於我的發現的詳細文章(並在此鏈接),以及exec如何幫助我解決問題:D – Sanjeev 2011-05-02 16:40:33

+0

@Sanjeev:很高興聽到它。當然,在大多數情況下,一個「陷阱」(錯誤goto':P)比'錯誤恢復下一個'要好得多。但它肯定會很好,得到實際相關的位的另一個總結,而不是堆積在許多小事情,以迫使它工作... – 2011-05-03 23:24:29

+0

@RubenBartelink關於http://geekswithblogs.net/dwdii /archive/2011/05/27/part-2-automating-a-visual-studio-build-with-powershell.aspx? – Kiquenet 2013-05-03 07:16:47