如何使用PowerShell的Invoke-Command捕获ScriptBlock调用的返回值

36

我的问题与这个问题非常相似,不过我尝试使用Invoke-Command来捕获ScriptBlock的返回代码(所以我不能使用-FilePath选项)。这是我的代码:

Invoke-Command -computername $server {\\fileserver\script.cmd $args} -ArgumentList $args
exit $LASTEXITCODE
问题是Invoke-Command无法捕获script.cmd的返回代码,因此我无法知道它是否失败。我需要知道script.cmd是否失败。我也尝试过使用New-PSSession(它可以让我在远程服务器上看到script.cmd的返回代码),但我找不到任何方法将其传递回我的调用PowerShell脚本以实际处理失败情况。
5个回答

47
$remotesession = new-pssession -computername localhost
invoke-command -ScriptBlock { cmd /c exit 2} -Session $remotesession
$remotelastexitcode = invoke-command -ScriptBlock { $lastexitcode} -Session $remotesession
$remotelastexitcode # will return 2 in this example
  1. 使用 new-pssession 创建一个新会话
  2. 在此会话中调用你的脚本块
  3. 从这个会话中获取 lastexitcode

这个可行。我不知道你可以像那样从会话中传递远程变量回本地脚本。谢谢! - Jay Spang
7
你可以尝试使用 $remotelastexitcode = invoke-command -ScriptBlock { cmd /c exit 2; $lastexitcode} -Session $remotesession 这段代码吗?由于你正在使用会话来执行多个命令,所以可能可以避免出现问题。 - manojlds
2
@manojlds 是的,在第一个脚本块中捕获 lastexitcode 也是可以的。 - jon Z
能否从使用-filepath参数的远程会话中检索最后一个退出代码,例如Invoke-Command -Session $Session -FilePath "FullStopBizTalkApp.ps1" -argumentlist $BizTalkMgmtDBConString,$ApplicationNameInBizTalk? - Rob Bowman
非常感谢 - 那真的对我有帮助! - AllDayPiano
@jonZ 很棒的回答!谢谢!它对我帮助很大!我只想为那些在任何脚本块中使用此功能的人提出一个安全建议:在最后使用 remove-pssession $remotesession 关闭会话!因为通常涉及凭据... - Beccari

9
$script = {
    # Call exe and combine all output streams so nothing is missed
    $output = ping badhostname *>&1

    # Save lastexitcode right after call to exe completes
    $exitCode = $LASTEXITCODE

    # Return the output and the exitcode using a hashtable
    New-Object -TypeName PSCustomObject -Property @{Host=$env:computername; Output=$output; ExitCode=$exitCode}
}

# Capture the results from the remote computers
$results = Invoke-Command -ComputerName host1, host2 -ScriptBlock $script

$results | select Host, Output, ExitCode | Format-List

主机名:HOST1
输出结果:无法找到主机badhostname。请检查名称并重试。
退出码:1

主机名:HOST2
输出结果:无法找到主机badhostname。请检查名称并重试。
退出码:1


3

最近我使用另一种方法来解决这个问题。脚本在远程计算机上运行产生的各种输出是一个数组。

$result = Invoke-Command -ComputerName SERVER01 -ScriptBlock {
   ping BADHOSTNAME
   $lastexitcode
}

exit $result | Select-Object -Last 1
$result 变量将包含 ping 输出消息和 $lastexitcode 的数组。如果远程脚本的退出代码是最后输出的,则可以从完整结果中获取它,无需解析。
要获取退出代码之前的其余输出,只需使用以下命令:
$result | Select-Object -First $(result.Count-1)

2

@jon Z的回答很好,但这个更简单:

$remotelastexitcode = invoke-command -computername localhost -ScriptBlock {
    cmd /c exit 2; $lastexitcode}

当然,如果你的命令会产生输出,那么你需要将其抑制或解析以获取退出代码,在这种情况下,@jon Z的答案可能更好。

1

最好使用return而不是exit

例如:

$result = Invoke-Command -ComputerName SERVER01 -ScriptBlock {
   return "SERVER01"
}

$result

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接