PowerShell退出代码 - 从MSBuild调用

时间:2011-04-28 19:57:07

标签: powershell msbuild

我正在从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

3 个答案:

答案 0 :(得分:15)

这个问题是主要搜索引擎的最佳答案。来自James Kovacs的best answer is this(名利双收 - 即他对PowerShell和MSBuild集成有点FizzBinned。)

总之,在ps1文件中:

  1. 在脚本的顶部粘贴$ErrorActionPreference='Stop',这不是默认值,即SilentlyContinue(接受的答案中的trap位具有相同的效果,但更为间接并且令人困惑)
  2. 坚持他的function exec {...(或使用psake本身)
  3. exec { x.exe }
  4. 中包装外部EXE的调用
  5. 不需要做任何明确的exit ...内容
  6. 默认错误处理将异常从ERRORLEVEL传播为powershell.exe myscript.ps1为1,即在MSBuild <Exec中,您不需要做任何诡计,告诉它忽略退出代码等(除非你想对特定的退出代码做一些条件,你想要做IgnoreExitCode="true"并用<Output元素捕获它)

    最后要理解的一点是,在PowerShell中,有一个$?是最后一个表达式的结果(如果你处于ErrorAction='Stop'模式则不相关)会随着每个表达式而变化你做的事情,而$ LastExitCode是系统中触发的最后一个.exe的'DOS'退出代码。 Details here - be sure to read the comments

答案 1 :(得分: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,即使Invoke-Command失败,$lastexitcode也设置为0!您可以通过执行echo %errorlevel%来测试cmd本身是否有效,并看到您获得1。

答案 2 :(得分:0)

我尝试了几种选择,但没有一种适合我。

要捕获msbuild目标上的powershell错误,最好的方法是从powershell脚本(如$ host.SetShouldExit($ remotelastexitcode))返回错误代码。

例如 test1.ps1

void call(char* filename){
    //call python script
}

值得一看的https://snagify.wordpress.com/2008/04/06/teambuild-powershell-and-exit-codes/