从PowerShell脚本返回退出代码

时间:2018-05-06 13:39:21

标签: powershell

我对从cmd.exe调用运行时从PowerShell返回退出代码值有疑问。我发现https://weblogs.asp.net/soever/returning-an-exit-code-from-a-powershell-script有帮助。但是,PowerShell代码的解决方案是添加一个函数。

function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode) exit }

生成:

ExitWithCode : The term 'ExitWithCode' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At C:\src\t\e\exit5.ps1:6 char:1
+ ExitWithCode -exitcode 12345
+ ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (ExitWithCode:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

但是,放置"退出"在新的线上工作。这只是一种语言异常吗?

function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode)
exit }

此外,此页面是从2010年开始的。这仍然是目前的状态吗?现在有更好/更简单的方法吗?

4 个答案:

答案 0 :(得分:5)

正如Guenther Schmitz所解释的那样,$host.SetShouldExit($exitcode)exit是两个不同的陈述,必须用换行符或分号分隔。

如果没有这种分离,您的代码应该抛出不同的错误,但是:

  

意外的令牌'退出'在表达或陈述中。

您发布的错误看起来更像是您尝试使用该功能而未先定义它。

该功能的目的是在退出脚本时设置正确的退出代码,无论脚本如何运行。通常,您可以像这样运行PowerShell脚本:

powershell.exe -File "C:\your.ps1"

在这种情况下,一个简单的exit $exitcode就足够了:

C:\> type test1.ps1
exit 23
C:\> powershell -File .\test1.ps1

C:\> echo %errorlevel%
23

但是,执行PowerShell脚本的另一种方法是-Command参数(因为PowerShell脚本可以直接从PowerShell运行)。 -File-Command参数之间的区别在于后者仅返回1或0(表示脚本是否以非零退出代码退出),而不是退出代码本身。< / p>

C:\> powershell -Command .\test1.ps1

C:\> echo %errorlevel%
1

完全省略参数时,PowerShell默认为-Command(允许您从命令行轻松运行PowerShell语句):

C:\> powershell .\test1.ps1

C:\> echo %errorlevel%
1

通过$host.SetShouldExit()定义退出代码可确保在通过powershell. -Command调用脚本时正确返回退出代码。但是,您仍然应该使用实际的退出代码退出,否则退出代码只有在通过powershell.exe -Command运行脚本时 才能设置,但在运行时脚本通过powershell.exe -File

C:\> type test2.ps1
function ExitWithCode($exitcode) {
  $host.SetShouldExit($exitcode)
  exit
}
ExitWithCode 23
C:\> powershell -File .\test2.ps1

C:\> echo %errorlevel%
0                                # ← exit without argument defaults to 0!

C:\> powershell -Command .\test2.ps1

C:\> echo %errorlevel%
23
C:\> type test3.ps1
function ExitWithCode($exitcode) {
  $host.SetShouldExit($exitcode)
  exit $exitcode
}
ExitWithCode 23
C:\> powershell -File .\test3.ps1

C:\> echo %errorlevel%
23

C:\> powershell -Command .\test3.ps1

C:\> echo %errorlevel%
23

答案 1 :(得分:3)

Guenther Schmitz's answer解决了您的直接语法问题,但请务必注意 {strong> $host.SetShouldExit()不是 ,而是Bruce Payette's answer所暗示的用户代码调用。

相反,PowerShell本身在内部使用它来响应用户代码中的exit语句

使用它的唯一可能原因是重新利用来实现变通方法,以围绕通过脚本调用脚本时退出代码报告的局限性-Command
PowerShell的CLI的(-c)参数

使用-Command时,脚本的特定非零退出代码始终会转换为1,因此特定的退出代码会丢失-有关退出代码处理的概述,请参见this answer在PowerShell中。

$host.SetShouldExit(),尽管不打算用于此目的,但还是要克服此限制,并确保脚本的退出代码也被报告为PowerShell进程的退出代码。

交互式PowerShell会话 调用脚本时,必须不要应用此解决方法,因为它将导致该会话作为整体立即退出,这是your follow-up question的主题。

可靠地检测通过-Command调用脚本的时间并不容易,而且很难使其完全可靠,如this answer中所示,您的后续问题。

不是更好的方法是使用$host.SetShouldExit()解决方法,而是执行以下操作。

  • 通过 -File CLI参数调用脚本,在这种情况下,无需任何解决方法: 只需在脚本中使用exit $n ,就会将$n报告为PowerShell进程的退出代码(假设$n是整数)。

  • 通过 -Command 进行调用时,请在命令字符串后跟 ; exit $LASTEXITCODE 进行脚本调用,以确保脚本的退出代码通过。

当然,您可能并不总是控制通过CLI调用脚本的方式。在这种情况下,workaround是值得考虑的。

答案 2 :(得分:1)

<form action="#" onsubmit="onSubmit(event)"> <input type="checkbox" name="checkbox" value="check" id="agree" /> I agree to the Terms <input type="submit" name="submit" value="submit" /> </form> <script> function onSubmit(event) { event.preventDefault(); // Do not submit the form, otherwise it will reload the page if (document.getElementById('agree').checked) { window.location.href = 'http://myURL.com'; } } </script> $host.SetShouldExit($exitcode)是两个必须分开的命令。要么返回(像你提到的那样)要么用分号:

exit

答案 3 :(得分:0)

从PowerShell返回退出代码的方法是执行exit $exitcode。在内部,当运行时处理exit关键字时,它将为您调用$host.SetShouldExit($exitcode)。但请注意,exit也会退出脚本,因此运行脚本非常重要。如果要运行从exit调用powershell.exe的脚本,请使用-File参数而不是{/ 1}},而不是

-Script