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

时间:2012-09-26 11:41:14

标签: powershell error-handling 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)

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

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

我的问题是:

以某种方式可以将Invoke-Command的ErrorVariable设置为ScriptBlock中的错误吗?

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

4 个答案:

答案 0 :(得分:17)

不,您无法将Errorvariable调用中的Invoke-Command设置为与脚本块中的相同。

但是,如果您的目标是“检测并处理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>
}

$results现在包含错误信息。

答案 1 :(得分:9)

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

$errortext

或更好,只是不要通过-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

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

答案 2 :(得分:0)

从最严格的意义上讲,我认为答案是否定的,你不能将Invoke-Command的ErrorVariable设置为脚本块内ErrorVariable的内容。 ErrorVariable仅适用于它附加的命令。

但是,您可以将脚本块中的变量传递给Invoke-Command的范围。在您的代码中,使用-ErrorVariable errortext运行New-Service命令。相反,通过在变量名称前加上“script:”来创建“脚本”范围内的变量,如下所示:-ErrorVariable script:errortext。这使得变量在脚本块以及内部可用。

现在您的最后一行Write-Host("Error out: " + $errortext)将输出脚本块内生成的错误。

更多信息herehere

答案 3 :(得分:0)

这几乎肯定不是“正确”的答案,但这是我希望Invoke-Command在脚本中引发错误时使用的方式。

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

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

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