拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 尝试使用BAT档案从PowerShell呼叫命令中捕获退出代码

尝试使用BAT档案从PowerShell呼叫命令中捕获退出代码

白鹭 - 2022-03-01 2129 0 0

我正在尝试从使用 Invoke-Command 在远程计算机上运行脚本块的 PowerShell 脚本中捕获退出代码。

首先是 BAT 档案:BAT 档案使用变量运行。脚本如下所示:

powershell.exe -noninteractive -noprofile -command "& {E:\Scripts\Check-Services_XXX.ps1 %1 }"
EXIT /B %errorlevel%

PowerShell 脚本如下所示:

param(
[string] $ip #IP address van server
)


$username = "DOMAIN\DOMAIN_USER"
$secpasswdfile = "E:\Location\DOMAINUSER_encrypted_password.txt"
$secpasswd = Get-Content $secpasswdfile | ConvertTo-SecureString
$credentials = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$soptions = New-PSSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck

Invoke-Command -ComputerName $ip -UseSSL -SessionOption $soptions -Credential $credentials -ScriptBlock `
{
# Start services
Start-Service -InputObject (Get-Service -Name IAS)

# Check services status

$checkservice = (get-service -Name IAS -ErrorAction SilentlyContinue)
if($checkservice.status -ne "Running"){$host.SetShouldExit(1)}

exit
}

问题是 ExitCode 没有被捕获回来,所以当 BAT 档案结束时,它以 0 结束。如果一切都在运行,就会出现这种情况。但是我故意将检查服务部分中的服务名称更改为肯定不存在的名称,但 BAT 档案仍然以 Exitcode 0 结尾

到目前为止已完成:尝试了此解决方案: 使用“invoke-command”捕获命令的回传码 - Powershell 2 但没有奏效:出现以下错误“不等于打开,您无法在会话中运行命令。 session state is Closing" 显然,当它退出错误时,会话已关闭,因此无法获取退出代码

也试过这个:Capture Write-Host output and exit code from Invoke-Command on a Remote System 但结果也一样;没有正确的退出代码(在 BAT 档案中应为 1 而不是 0)

解决方案!

感谢@js2010 和@mklement0;它现在就像一个魅力!

这是 BAT 档案:

powershell.exe -noprofile -File "E:\Scripts\Check-Services_XXX.ps1" "%1" "%2"
EXIT /B %errorlevel%

这是最终为我解决的 PowerShell 代码:

param(
[string] $ip,       #IP address of checked server
[string] $service ) #Service name

$username = "DOMAIN\USER"
$secpasswdfile = "E:\Scripts\Credentials\DOMAIN-USER_encrypted_password.txt"
$secpasswd = Get-Content $secpasswdfile | ConvertTo-SecureString
$credentials = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$soptions = New-PSSessionOption -SkipCACheck -SkipRevocationCheck -SkipCNCheck
$session = New-PSSession -ComputerName $ip -UseSSL -SessionOption $soptions -Credential $credentials

# Start services
Invoke-Command -Session $session -ScriptBlock { Start-Service -Name $using:service }

# Check services status
$checkservice = Invoke-Command -Session $session { Get-Service -name $using:service | where status -eq running }
if (! $checkservice) { 
  write-output ("Error 1, Service '"   $service   "' not running or not found.")
  exit 1
}

我在将变量传递给远程命令时遇到了一些问题,这个链接帮助了我(https://powershellexplained.com/2016-08-28-PowerShell-variables-to-remote-commands/

uj5u.com热心网友回复:

您必须在呼叫命令之外运行退出命令。

# check-service.ps1
$result = invoke-command localhost { get-service appxsvc | 
  where status -eq running }
if (! $result) { 
  exit 1
}

uj5u.com热心网友回复:

更改您的呼叫powershell.exe以使用-File CLI自变量:

powershell.exe -NoProfile -File "E:\Scripts\Check-Services_XXX.ps1" "%1"
EXIT /B %errorlevel%

这样,.ps1脚本的退出代码被正确地中继为powershell.exe退出代码。

此外,作为js2010 的回答说明,您需要使用脚本块之外的$host.SetShouldExit(1)呼叫,因为后者是远程执行的由于下面解释的原因,它是优选的。Invoke-Commandexit 1


通常来说,一般来说:

  • 没有理由使用-Command( -c) CLI 自变量"& { ... }"来呼叫代码 - 只需"..."直接使用旧版本的CLI 档案错误地建议这& { ... }是必需的,但这已得到纠正。

  • 不仅没有"& { ... }"必要,而且总是将退出代码重置为0.

至于您使用$host.SetShouldExit(1)退出代码请求退出的使用1(撇开远程呼叫无效):

  • 它通常不被设计为从用户代码中呼叫,如本答案中所述

有关 PowerShell 中退出代码的一般信息,请参阅此答案

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *