在Invoke-Command Cmdlet中处理ScriptBlock中的错误

fla*_*ayn 10 error-handling powershell invoke-command

我正在尝试使用powershell在远程计算机上安装服务.

到目前为止,我有以下内容:

Invoke-Command -ComputerName  $remoteComputerName -ScriptBlock {
         param($password=$password,$username=$username) 
         $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
         $credentials = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
         New-Service -Name "XXX" -BinaryPathName "c:\XXX.exe" -DisplayName "XXX XXX XXX" -Description "XXXXXX." -Credential $credentials -ErrorVariable errortext 
         Write-Host("Error in: " + $errortext)
        } -ArgumentList $password,$username -ErrorVariable errortext 


Write-Host("Error out: " + $errortext)
Run Code Online (Sandbox Code Playgroud)

当执行New-Service时出错时,$ errortext ErrorVariable在ScriptBlock中正确设置,因为文本:"错误:显示错误.

Invoke-Command的ErrorVariable没有设置(我预期的).

我的问题是:

是否有可能将Invoke-Command的ErrorVariable设置为我在ScriptBlock中获得的错误?

我知道我也可以使用InstalUtil,WMI和SC来安装服务,但目前这不相关.

lat*_*kin 17

不,您无法ErrorvariableInvoke-Command调用中获取与scriptblock中相同的设置.

但是,如果您的目标是"检测并处理scriptblock中的错误,并将错误返回给Invoke-Command调用者的上下文",那么只需手动执行:

$results = Invoke-Command -ComputerName server.contoso.com -ScriptBlock {
   try
   {
       New-Service -ErrorAction 1
   }
   catch
   {
       <log to file, do cleanup, etc>
       return $_
   }
   <do stuff that should only execute when there are no failures>
}
Run Code Online (Sandbox Code Playgroud)

$results 现在包含错误信息.

  • @latkin,你应该在这个答案中指出这个工作的原因是你正在处理一个正常的非终止错误并将其转换为终止错误,以便你可以用try/catch语句捕获错误.将值"Stop"用于-ErrorAction而不是1将更清楚. (10认同)

Kei*_*ill 10

Invoke-Command参数列表是单向交易.您可以在脚本中输出错误变量,例如在scriptblock的最后一行:

$errortext
Run Code Online (Sandbox Code Playgroud)

或者更好,只是不要通过-ErrorVariable捕获错误.脚本块输出(包括错误)将甚至通过远程连接返回到调用者.

C:\> Invoke-Command -cn localhost { Get-Process xyzzy } -ErrorVariable errmsg 2>$null
C:\> $errmsg
Cannot find a process with the name "xyzzy". Verify the process name and call the cmdlet again.
    + CategoryInfo          : ObjectNotFound: (xyzzy:String) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
    + PSComputerName        : localhost
Run Code Online (Sandbox Code Playgroud)

一般来说,我认为在错误流上保留错误要好得多,与正常输出分开.

  • 在这种情况下,执行Invoke-Command后立即检查`$?`.这是确定命令是否失败或成功的典型方法. (3认同)

Ada*_*m S 6

这几乎肯定不是“正确”的答案,但当我希望 Invoke-Command 在脚本中抛出错误时,我会使用这个答案。

$error.Clear()
Invoke-Command -ComputerName localhost -ScriptBlock {Command-ThatFails}
if ($error.Count -gt 0) { throw $error[0] }
Run Code Online (Sandbox Code Playgroud)

如果您想将错误保留在变量中,可以执行以下操作:

$error.Clear()
Invoke-Command -ComputerName localhost -ScriptBlock {Command-ThatFails}
if ($error.Count -gt 0) { $myErrorVariable = $error[0] }
Run Code Online (Sandbox Code Playgroud)