从PowerShell脚本返回退出代码

lit*_*lit 1 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 }
Run Code Online (Sandbox Code Playgroud)

产生:

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
Run Code Online (Sandbox Code Playgroud)

但是,将“出口”放在新行上是可行的。这只是语言异常吗?

function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode)
exit }
Run Code Online (Sandbox Code Playgroud)

另外,此页面是2010年以来的内容。这仍是当前状态吗?现在有更好/更简便的方法吗?

Ans*_*ers 9

如京特施米茨已经解释的,$host.SetShouldExit($exitcode)并且exit是必须要么与换行或分号隔开2个不同的语句。

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

表达式或语句中出现意外的标记“退出”。

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

该功能的目的是在退出脚本时设置适当的退出代码,而不管脚本的运行方式如何。通常,您将运行以下PowerShell脚本:

powershell.exe -File "C:\your.ps1"
Run Code Online (Sandbox Code Playgroud)

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

C:\> 输入test1.ps1
出口23
C:\> powershell-文件。\ test1.ps1

C:\> 回声%errorlevel%
23

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

C:\> powershell-命令。\ test1.ps1

C:\> 回声%errorlevel%
1个

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

C:\> powershell。\ test1.ps1

C:\> 回声%errorlevel%
1个

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

C:\> 输入test2.ps1
函数ExitWithCode($ exitcode){
  $ host.SetShouldExit($ exitcode)
  出口
}
ExitWithCode 23
C:\> powershell-文件。\ test2.ps1

C:\>回声%errorlevel%
0                                #←不带参数退出默认为0!

C:\> powershell-命令。\ test2.ps1

C:\> 回声%errorlevel%
23
C:\> 输入test3.ps1
函数ExitWithCode($ exitcode){
  $ host.SetShouldExit($ exitcode)
  退出$ exitcode
}
ExitWithCode 23
C:\> powershell-文件。\ test3.ps1

C:\>回声%errorlevel%
23

C:\> powershell-命令。\ test3.ps1

C:\> 回声%errorlevel%
23


mkl*_*nt0 8

冈瑟施米茨的回答解决您的眼前语法问题,但它是要注意,重要的$host.SetShouldExit()认为由用户代码调用,通过所暗示的布鲁斯·帕耶特的答案

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

使用它的唯一可能的原因是,当通过PowerShell 的CLI的 ( ) 参数调用脚本时,将其重新用于实现解决退出代码报告限制的变通方法-Command
-c

使用-Command,脚本的特定非零退出代码始终会转换为1,因此特定退出代码会丢失 - 请参阅此答案以了解 PowerShell 中退出代码处理的概述。

$host.SetShouldExit(),尽管并非用于此目的,但碰巧克服了此限制并确保脚本的退出代码也报告为 PowerShell 进程的退出代码。

当从交互式 PowerShell 会话调用脚本时,不得应用解决方法,因为它会导致整个会话立即退出,这是您后续问题的主题。

-Command但是,如对后续问题的回答所示,可靠检测何时通过调用脚本是非常重要的,并且很难完全可靠。

更好的办法是使用的$host.SetShouldExit()解决方法并执行以下操作来代替。

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

  • 调用 via 时-Command,请; exit $LASTEXITCODE在命令字符串中跟随脚本调用 with ,以确保传递脚本的退出代码。

当然,您可能无法始终控制通过 CLI 调用脚本的方式;在这种情况下,解决方法值得考虑。


Gue*_*itz 6

$host.SetShouldExit($exitcode)exit是两个必须分开的命令。要么返回(如您所提到的)或分号:

function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode); exit }
Run Code Online (Sandbox Code Playgroud)