【问题标题】:How to get the error code (ErrorLevel) from PowerShell into Windows command prompt?如何从 PowerShell 获取错误代码 (ErrorLevel) 到 Windows 命令提示符中?
【发布时间】:2016-04-29 16:27:43
【问题描述】:

我正在尝试通过 Windows 命令提示符启动 PowerShell 命令以将文本替换为文件。问题是我总是得到 ErrorLevel = 0 即使我的 PowerShell 命令不起作用。 我的问题是当我通过cmd 启动 PowerShell 时,如何将错误代码输入 ErrorLevel? 请注意,我想通过 Windows 命令提示符而不是通过创建脚本来实现这一点。

这是我所说的一个例子。打印屏幕中的错误是故意通过选择一个不存在的文件来向您显示即使出现错误,ErrorLevel 也等于 0。

我使用的命令如下(我试过$LastExitCode$ExitCode):

powershell -NonInteractive -NoProfile -Command "(Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref; exit $LastExitCode"

但我也尝试过:

powershell -NonInteractive -NoProfile -Command "(Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref; exit $ExitCode"

根据 majkinetor 的评论,我尝试了以下方法,但效果不佳:(,即使在 powershell 中发生错误,我也会在 Dos 中不断收到 ErrorLevel 0。

powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref } catch {exit $LastExitCode}"

可以清楚的看到文件名相关的错误不存在,但错误级别始终为0。

我想要的是为执行 PowerShell 命令时发生的每个错误获取除 0 以外的错误代码。

根据我读到的一些 cmets,我想说:我想通过 PowerShell 和 Dos 命令而不是用不同的方式来制作它。我不想制作自己的错误代码或个性化的错误管理!我想要的是当我的powershell(代码,脚本等)发生错误时,Dos的错误级别会得到这个错误代码(我不想制作自己的代码)。 欢迎有答案的人并感谢他们,但那些在这里只是通过要求更改我想要的内容或删除图片等来评论无用的 cmets...请不要发表评论,除非提供帮助和回答我的问题,而不是提出其他问题,我正在寻求有关特定问题的帮助,请不要将主题更改为其他内容。本网站的想法是提供帮助,而不是添加无用和无用的 cmets。

【问题讨论】:

  • @Bill_Stewart,当我们寻求帮助时,并不是为了得到关于其他事情的答案......你的评论根本没有帮助......如果我想用不同的方式做到这一点我不会问我的问题
  • @KenWhite Personnaly 当我阅读问题并想提供帮助时,我更喜欢打印屏幕而不是代码...无论如何我会裁剪图像,但我不会删除它们...谢谢反正
  • 太棒了。你一个人站着。我给了你一长串这个网站不喜欢图片的原因,显然你没有读过它。避免在图像中使用代码的最大原因是人们无法复制并粘贴它以尝试提供帮助,而且大多数人都不愿意重新输入。因此,如果您想减少(或至少延迟)获得帮助的机会,请继续在图片中发布代码。
  • @Bill_Stewart 当您不了解公司的环境和询问者等时,您无法判断...如果您有问题的答案,请给出,如果您没有没关系,不需要让这个人做其他事情......如果我想要或可以用不同的方式做到这一点,我不会在这里问我的问题......感谢您尊重人们的问题。我知道我为什么要求这样做,我不想写 5 页来解释原因,我试图直接去找目标并提出一个直接的问题..
  • 你得到了零,因为这是你传递的值。如果您想使用任一变量作为退出代码,您必须将它们设置为某个值。

标签: windows powershell cmd errorlevel


【解决方案1】:

在 cmd.exe shell 中试试这个代码:

C:> powershell -noprofile -command " try { 1/0 } catch {exit 22}"

C:> echo %errorlevel%
22

所以,将您的命令添加到 try 块中。如果碰巧你调用了非 powershell 命令,你可以exit $LastExitCode(但在 try 块内)。


编辑

好的,我知道你的非工作代码发生了什么,它从未通过捕获块,因为 Get-Content 产生non-terminating error。您必须注意这一点:

C:> Powershell -Command "try { (Get-Content HvsvmAppserver.ref -ea stop) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref -ea stop } catch {$_; exit 123 }"

Get-Content : Cannot find path 'C:\Users\majkinetor\HvsvmAppserver.ref' because it does not exist.
At line:1 char:8
+ try { (Get-Content HvsvmAppserver.ref -ea stop) -replace '-Dfr.base0. ...
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\majkinetor\HvsvmAppserver.ref:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

C:> echo %errorlevel%
123

注意我添加到两个命令中的-ea stop(比ErrorAction 更短)。我的解决方案第一次是正确的,但是,您需要了解脚本也必须正确设计。您可能还想使用 trap 代替 catch,但您仍然必须使用 EA 止损。也许不太依赖脚本的最短通用解决方案是:

   $ErrorActionPreferance = 'Stop'
   <your script goes here, no need for -ea stop in it>
   trap { exit 123 }

如果有问题的脚本更改$ErrorActionPreference(这种情况很少发生),这将不起作用,但在所有其他情况下都会起作用。

【讨论】:

  • 非常感谢,我明天上班试试,如果解决了我的问题会告诉你。
  • 不知道如果我做得好,但我尝试并不断得到错误级别 0 ...这是我使用的命令。 powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref } catch {退出 $LastExitCode}"
  • 我什至尝试过这个(即使我不想要自定义错误)并且我不断收到错误级别 0 .... 不知道那些对你的答案投票 +2 的人,如果他们测试了它或只是甚至未经测试就投票... powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -编码 ASCII HvsJvmAppserver.ref } catch {exit 12345}"
  • 你做得不对。不要返回exit $LastExitCode,在你的情况下它总是0。由于您使用了 posh cmdlet,它根本不返回错误级别,而是返回错误对象$_。以exit 1 为例。
  • 正如您在评论上方的代码中看到的那样,我没有使用 $LastExitCode,我输入了退出 12345,但我仍然得到 0!
【解决方案2】:

因此,根据我的评论将此作为答案:

你得到了零,因为这是你传递的值。如果你 想要使用您的任一变量作为退出代码,您必须 设置它们。

您的回复:

@ShawnMelton 谢谢,但我还没弄好....我不想做 我自己的错误代码或个性化的错误管理!我想要的只是 当我的powershell(代码、脚本等)发生错误时, Dos 的错误级别得到这个错误代码(我不想让我的 自己的代码)。你能用代码说明你的意思吗?我可能有 不明白你的评论?感谢您的帮助,这很好 你身边。

当您调用powershell.exe 时,它将返回一个退出代码返回到命令提示符,始终为零 (0)。即使您执行不正确的 PowerShell 代码,它也始终为零。 powershell.exe 本身正在成功执行您传递给它的任何命令,因此除非可执行文件本身由于某种原因出错,否则您总是得到零。如果您希望PowerShell.exe 返回非零值,则需要在 PowerShell 命令中使用exit xx,其中xx 是一个整数。

不尝试从命令提示符调用 PowerShell 的意义仍然存在,无论您是否愿意。您不能保证即使使用 exit 99 之类的东西总是会覆盖返回零的可执行文件......这就是它的工作方式。当我在装有 Windows 10 的笔记本电脑上尝试它时,我得到了各种结果。我可以说我之前在生产中使用过技术,当时我不得不从 SSIS 包调用 PowerShell 脚本,它达到了目的。但是在那种情况下,我没有从批处理文件中调用它,所以它按预期工作。

【讨论】:

  • @Shwan Melton,非常感谢。现在我明白了为什么我总是 0。我不明白的第二部分是为什么如果我把出口 99,我不会得到它 99 ?请您再次澄清我的答案的第二部分吗?至于我为什么要通过dos这样做,那是因为在我的公司他们有很长的.cmd,如果我想修改任何东西,我必须使用这个.cmd并且不能编写外部脚本等......否则我本来可以用 .vbs 做我想做的事,但是我们的规则很复杂,我不能做我想做的所有事情,我必须在唯一的 .cmd 中做到这一点
  • 通过命令提示符 (DOS) 执行 PowerShell 脚本并不能保证您可以将退出代码更改为零以外的任何值。
  • 所以得出结论我不能做我想做的事,或者说清楚,我可以做到,但我不能保证管理潜在的错误......我做得好吗?时间 ? :)
  • 我确信这是错误的 - 连续构建取决于 powershell 在失败时返回 0 以外的值以停止构建。我已经多次使用这种方法并且它有效。我给出的例子是在 Win7,8,10 和 Powershell 4,5 上测试的。
  • 实际上退出记录为设置 ErrorLevel:docs.microsoft.com/en-us/powershell/module/…
【解决方案3】:

@majkinetor 的建议绝对有效。我的意思是这个:

powershell -Command "try {(gc "C:\test.txt" -ea stop) -creplace 'test', 'work' | Out-File -encoding ASCII "C:\test.txt" -ea stop} catch{ exit 1}"

如果文件路径正确,则替换字符串。如果文件路径不正确 - 使用上面的 sn -p 将 cmd 会话中的错误级别设置为 1。

我遇到的问题是,我希望它使 Jenkins 构建失败。我使用构建步骤执行 Windows 批处理命令,诀窍是,如果您希望它在错误时使构建失败,您只需要使用上述命令。如果您之后有另一个并且它成功 - 构建成功。

【讨论】:

    【解决方案4】:

    如果最后使用外部命令,它将设置错误级别。我用“^”引用管道。

    powershell echo hi ^| findstr hi2
    

    或者你可以测试$?并以非零数退出:

    powershell 1/0; if (! $?) { exit 1 } 
    

    实际上,如果 LAST cmdlet 引发错误,无论是否终止,它都应该设置 cmd 错误级别。

    你可以做这样的事情,然后退出错误的数量。

    powershell $errorcount = $error.count; 1/0; echo hi; exit $error.count - $errorcount
    

    脚本终止错误将设置错误级别:

    powershell throw 'hi'
    

    更多地考虑最初的问题。如果您不使用括号,则如果找不到文件,则会设置错误级别,因为当前管道将出现异常。但是输出文件必须不同。将其作为脚本运行不会产生相同的结果(unix 也不会)。

    powershell "get-content foo2 | foreach { $_ -replace 'a','b' } | set-content foo3"
    
    get-content : Cannot find path 'C:\Users\admin\foo2' because it does not exist.
    At line:1 char:1
    + get-content foo2 | foreach { $_ -replace 'a','b' } | set-content foo3
    + ~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\Users\admin\foo2:String) [Get-Content], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
    
    
    echo %errorlevel%
    
    1
    

    【讨论】:

      【解决方案5】:

      考虑使用选项 -file 而不是 -command。 通过使用 -file 选项,您将获得您在代码中指定的任何值, 而 -command 选项将为您提供 0 或 1。

      试试这个场景:

      cmd.exe

      cd %userprofile%\desktop

      echo $temp=999;write-host $temp;exit $temp > test.ps1

      回显 %errorlevel%

      0

      powershell .\test.ps1

      999

      回显 %errorlevel%

      1

      powershell -command .\test.ps1

      999

      回显 %errorlevel%

      1

      现在...

      powershell -file .\test.ps1

      999

      回显 %errorlevel%

      999

      祝你好运!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-09
        • 1970-01-01
        • 2014-05-10
        • 2011-02-12
        • 2010-11-22
        • 2022-01-25
        相关资源
        最近更新 更多