Handle errors in ScriptBlock in Invoke-Command Cmdlet
No, you can't get the Errorvariable
from the Invoke-Command
call to be set the same as in the scriptblock.
But if your goal is "detect and handle errors in the scriptblock, and also get errors returned back to the context of the Invoke-Command
caller" then just do it manually:
$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
now contains the error information.
The Invoke-Command argument list is a one way deal. You can either output the error variable in the script e.g. on the last line of the scriptblock put:
$errortext
or better yet, just don't capture the error via the -ErrorVariable at all. The scriptblock output, including errors, will flow back to the caller even over a remote connection.
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
In general, I think it is much better to keep errors on the error stream, separated from the normal output.
This is almost certainly not the "correct" answer, but this is what I use when I want Invoke-Command to throw an error in the script.
$error.Clear()
Invoke-Command -ComputerName localhost -ScriptBlock {Command-ThatFails}
if ($error.Count -gt 0) { throw $error[0] }
If you wanted to keep the error in a variable, you could do the following:
$error.Clear()
Invoke-Command -ComputerName localhost -ScriptBlock {Command-ThatFails}
if ($error.Count -gt 0) { $myErrorVariable = $error[0] }