我对从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年以来的内容。这仍是当前状态吗?现在有更好/更简便的方法吗?
如京特施米茨已经解释的,$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
冈瑟施米茨的回答解决您的眼前语法问题,但它是要注意,重要的$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 调用脚本的方式;在这种情况下,解决方法值得考虑。
$host.SetShouldExit($exitcode)
和exit
是两个必须分开的命令。要么返回(如您所提到的)或分号:
function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode); exit }
Run Code Online (Sandbox Code Playgroud)