【问题标题】:PowerShell exit code - Calling from MSBuildPowerShell 退出代码 - 从 MSBuild 调用
【发布时间】:2011-04-28 19:57:07
【问题描述】:

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

【问题讨论】:

标签: powershell msbuild


【解决方案1】:

这个问题是主要搜索引擎上的最佳答案。来自 James Kovacs 的 best answer is this(以 psake 成名——也就是说,他在 PowerShell 和 MSBuild 集成方面有点像 FizzBinned)。

总之,在一个 ps1 文件中:

  1. 在脚本顶部粘贴$ErrorActionPreference='Stop',因此它不是默认值,即SilentlyContinue(已接受答案中的trap 位具有相同的效果,但更为间接和混乱)
  2. 坚持他的function exec {...(或使用psake本身)
  3. 将外部 EXE 调用包装在 exec { x.exe } 中
  4. 不需要做任何明确的exit ... 东西

默认错误处理将异常向上传播为来自powershell.exe myscript.ps1 的ERRORLEVEL 1,即在MSBuild &lt;Exec 中,您不需要做任何技巧来告诉它忽略退出代码等。(除非你想在特定的退出代码上做一些事情,你想做IgnoreExitCode="true"并用&lt;Output元素捕获它)

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

【讨论】:

  • 甜蜜!谢谢你提供的详情。我正在使用博客链接中提到的“执行函数”代码来捕获从 myscript.ps1 在远程计算机中调用的另一个 PS 脚本(remoteinvoke.ps1)的错误。 Trap 在这些情况下不起作用。我会写一篇关于我的发现以及 exec 如何帮助我解决问题的详细帖子(并在此处链接):D
  • @Sanjeev:很高兴听到这个消息。当然,在大多数情况下,trap (on error goto :P) 并不比 on error resume next 好多少。但是,获得另一个实际相关的位的摘要肯定会很好,而不是堆积很多小东西来强迫它工作......
  • @RubenBartelink geekswithblogs.net/dwdii/archive/2011/05/27/… 是怎么回事?
  • @Kiquenet 嗯...有硬编码的 C 驱动器路径并且没有错误处理...无论如何,对我来说,如果您采用那条路线,请坚持使用经过验证的路线,例如stackoverflow.com/a/3465029/11635
【解决方案2】:

将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。

【讨论】:

  • 不走运!还是一样。直接从 powershell 窗口运行时退出代码为 255
  • 感谢您的更新。陷阱 { } 成功了!现在 MSbuild 说“构建失败”。问题是它没有显示 $._Exception.Message 的想法。它显示的只是'代码' C:\scripts\testmsbuild.proj(12,3): error MSB3073: The command "powershell.exe c:\scripts\test.ps1" exited with code 1 'code'。不过,战斗已经结束了一半:)
  • 你能在没有 Write-Host 的情况下试试看...比如trap {$_.Exception.Message; exit 1; continue}
  • 此外,我还要添加我必须进行的其他更改才能使其正常工作。 ' ' testmsproj.proj 中的代码必须替换为 ''
【解决方案3】:

我尝试了几个选项,但没有一个适合我。

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

例如 test1.ps1

function CallFromMSBuild {

   Invoke-command {Powershell.exe C:\a.ps1} -computername $computers
   $host.SetShouldExit(1)
} 

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

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

【讨论】:

    猜你喜欢
    • 2021-12-04
    • 2016-05-20
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多