I have a little function to get all printer objects from a print server, the cmdlet throws an error if the spooler service is not available (e.g. the hostname is wrong). I want to catch that error message with a try catch, but it wont catch? Can someone explain this behavior to me?
Code:
Function GetAllPrinters
{
param
(
[Parameter(Mandatory=$true)]
[string]$PrintServerHostName
)
try {
$Printers = Get-Printer -ComputerName $PrintServerHostName
}
catch {
Write-Host "Could not receive information from the print server $PrintServerHostName."
exit 1001
}
return $Printers
}
Error Message:
Get-Printer : Der Spoolerdienst ist nicht erreichbar. Stellen Sie sicher, dass der Spoolerdienst ausgeführt wird.
In C:\Users\f.zedler\Desktop\GetPrintServerStatus.ps1:34 Zeichen:21
+ $Printers = Get-Printer -ComputerName $PrintServerHostName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (MSFT_Printer:ROOT/StandardCimv2/MSFT_Printer) [Get-Printer], CimException
+ FullyQualifiedErrorId : HRESULT 0x800706ba,Get-Printer
You're running into the concept of a Terminating versus a non-terminating error.
Some functions can throw an error but still continue without any issues, they might just throw an error to the error stream and keep on trucking. We'd call these a non-terminating error.
Others could leave you in a bad situation or cause issues, and it'd be better for them to error and stop. We call these terminating errors.
Terminating error have the nice value-add in that they are capable of triggering a try/catch block, while most other errors will not.
This function seems to be throwing a non-terminating error, which ignores try/catch blocks. You can override this though, by specifying a choice for -ErrorAction, which is a common parameter, one that's available for all cmdlets.
Your choices are this:
Inquire - ask you to continue or not
Continue - keep on trucking but write out error messages
SilentlyContinue - keep on trucking but sweep the error under the rug (silently!)
STOP - this is the one you want
So, in conclusion, since it looks like your function is ignoring your try/catch block, try and add -ErrorAction STOP. That will probably solve this problem.
Get-Printer -ErrorAction Stop
Try it with Get-Printer -ComputerName $PrintServerHostName -ErrorAction Stop or set $erroractionpreference to stop.
FYI
on my script below, I had to move the "-erroraction stop" option before the first pipe symbol.
$e=Get-Printer -ComputerName $lbpclist.SelectedItem -ErrorAction stop | Where-Object {$_.Name -like $txtPrinterName.Text
Related
This question already has answers here:
Try/catch does not seem to have an effect
(7 answers)
Closed 3 years ago.
I am trying to handle setting a PowerShell variable from a registry key.
So I use a try{} catch {} to get rid of eventual errors in case the key doesn't exists. However, I still get the error output on console.
$ZZ_ConVTL = try { (Get-ItemProperty -path "HKCU:\Console" -name VirtualTerminalLevel).VirtualTerminalLevel } catch { "N/A" }
...
# Output:
Get-ItemProperty : Property VirtualTerminalLevel does not exist at path HKEY_CURRENT_USER\Console.
At C:\Users\Administrator\Documents\xxxx\xxxx.ps1:181 char:32
+ ... = try { (Get-ItemProperty -path "HKCU:\Console" -name VirtualTermi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (VirtualTerminalLevel:String) [Get-ItemProperty], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
How can I handle and avoid this error from showing up in the console?
What your Get-ItemProperty call emits is a non-terminating error, whereas try / catch only catches terminating errors.
Non-terminating errors are far more common that terminating ones.
Use common parameter -ErrorAction Stop to promote (the first) non-terminating error generated by a cmdlet to a terminating one that try / catch handles.
You can generally achieve the same effect by setting preference variable
$ErrorActionPreference = 'Stop' beforehand, but note that doing so has no effect on calls to external programs and on functions implemented in modules.
See also:
The about_Try_Catch_Finally help topic.
A description of the fundamental error types in the context of guidance for command authors on when to emit a terminating vs. a non-terminating error: this answer.
A comprehensive overview of PowerShell's surprisingly complex error handling: this GitHub docs issue.
This question already has answers here:
Try/catch does not seem to have an effect
(7 answers)
Closed 3 years ago.
I am trying to handle setting a PowerShell variable from a registry key.
So I use a try{} catch {} to get rid of eventual errors in case the key doesn't exists. However, I still get the error output on console.
$ZZ_ConVTL = try { (Get-ItemProperty -path "HKCU:\Console" -name VirtualTerminalLevel).VirtualTerminalLevel } catch { "N/A" }
...
# Output:
Get-ItemProperty : Property VirtualTerminalLevel does not exist at path HKEY_CURRENT_USER\Console.
At C:\Users\Administrator\Documents\xxxx\xxxx.ps1:181 char:32
+ ... = try { (Get-ItemProperty -path "HKCU:\Console" -name VirtualTermi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (VirtualTerminalLevel:String) [Get-ItemProperty], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
How can I handle and avoid this error from showing up in the console?
What your Get-ItemProperty call emits is a non-terminating error, whereas try / catch only catches terminating errors.
Non-terminating errors are far more common that terminating ones.
Use common parameter -ErrorAction Stop to promote (the first) non-terminating error generated by a cmdlet to a terminating one that try / catch handles.
You can generally achieve the same effect by setting preference variable
$ErrorActionPreference = 'Stop' beforehand, but note that doing so has no effect on calls to external programs and on functions implemented in modules.
See also:
The about_Try_Catch_Finally help topic.
A description of the fundamental error types in the context of guidance for command authors on when to emit a terminating vs. a non-terminating error: this answer.
A comprehensive overview of PowerShell's surprisingly complex error handling: this GitHub docs issue.
This question already has answers here:
Try/catch does not seem to have an effect
(7 answers)
Closed 3 years ago.
I am trying to handle setting a PowerShell variable from a registry key.
So I use a try{} catch {} to get rid of eventual errors in case the key doesn't exists. However, I still get the error output on console.
$ZZ_ConVTL = try { (Get-ItemProperty -path "HKCU:\Console" -name VirtualTerminalLevel).VirtualTerminalLevel } catch { "N/A" }
...
# Output:
Get-ItemProperty : Property VirtualTerminalLevel does not exist at path HKEY_CURRENT_USER\Console.
At C:\Users\Administrator\Documents\xxxx\xxxx.ps1:181 char:32
+ ... = try { (Get-ItemProperty -path "HKCU:\Console" -name VirtualTermi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (VirtualTerminalLevel:String) [Get-ItemProperty], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
How can I handle and avoid this error from showing up in the console?
What your Get-ItemProperty call emits is a non-terminating error, whereas try / catch only catches terminating errors.
Non-terminating errors are far more common that terminating ones.
Use common parameter -ErrorAction Stop to promote (the first) non-terminating error generated by a cmdlet to a terminating one that try / catch handles.
You can generally achieve the same effect by setting preference variable
$ErrorActionPreference = 'Stop' beforehand, but note that doing so has no effect on calls to external programs and on functions implemented in modules.
See also:
The about_Try_Catch_Finally help topic.
A description of the fundamental error types in the context of guidance for command authors on when to emit a terminating vs. a non-terminating error: this answer.
A comprehensive overview of PowerShell's surprisingly complex error handling: this GitHub docs issue.
I've got a script that does some server maintenance. Part of the job is to stop and restart services on the host server. The easiest way to tell when the service is fully back online again is attempt to connect to the admin port. Once you're able to connect to the admin port, than the service is up and ready for business. Simple enough. This bit of code will loop until it's back online:
function test-port {
$PortProbe = New-Object Net.Sockets.TcpClient
$ErrorActionPreference = "SilentlyContinue"
while ($PortProbe.Connected -eq 0){
$PortProbe.Connect("localhost",3041)
write-host "Server is off line... waiting for it to come online."
sleep 1
}
write-host "Server is back online!"
$ErrorActionPreference = "Continue"
$PortProbe.Close()
}
test-port
So in my script I do my work, restart services and then call "test-port" to have the script to wait for the service to come back online before proceeding.
The problem I'm running into is if I have a generic trap in the script, it's trapping the connection error when the port isn't ready yet.
Exception calling "Connect" with "2" argument(s): "No connection could be made because the target machine actively refused it 127.0.0.1:3041"
At line:6 char:27
+ $PortProbe.Connect <<<< ("localhost",3041)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
I've got a trap statement at the end in case some really bizarre error happens, it'll kick off an e-mail alert. But it breaks the functionality of the test-port function.
In theory, I could trap this specific TCP/IP connection error and tell it to just continue on like nothing had happened, but I can't figure out how to tell what the class of the error message is. I thought it would be something like this:
trap [Net.Sockets.TcpClient] { #Don't Panic
}
But that's not right.
Any suggestions? Do I need to handle this completely differently?
Rather than dropping to sockets, why not use the Get-Service cmdlet in a loop to check the service's status e.g.:
do {
$svc = Get-Service -ComputerName Localhost w3svc
$connected = $false
if ($svc -and $svc.Status -eq 'Running') {
$connected = $true
}
Start-Sleep -Milliseconds 500
} while (!$connected)
I've written a function to wrap the the new-cssipdomain cmdlet with a try/catch block incase the sip domain already exists.
Code is:
function LHP-AddSIPDomain
{
param ( [string] $SIPDomain)
try
{
New-cssipdomain -id $SIPDomain
}
catch
{
Write-host "Lync specific exception occured adding SIP domain"
Write-host "Exception String:"+$_.Exception.Message
exit
}
}
LHP-AddSIPDOmain -SipDomain "Test206.com"
The output when the domain already exists is:
New-CsSipDomain : "SipDomain" with identity "Test206.com" already exists. To modify
the existing item, use the Set- cmdlet. To create a new item, use a different
identity. Parameter name: Identity
At S:\Scripts\LHP-AddSIPDomain.ps1:33 char:26
+ New-cssipdomain <<<< -id $SIPDomain
+ CategoryInfo : InvalidArgument: (Test206.com:String) [New-CsSipDomain],
ArgumentException
+ FullyQualifiedErrorId :
InvalidIdentity,Microsoft.Rtc.Management.Xds.NewOcsSipDomainCmdlet
This should be caught by the try/catch block.
I've tried adding the [system.exception] to the catch statement. I'ev also tried setting $erroraction=”Stop”. Neither made any different, the try/catch statement seems to be being ignored. I've used this type of code structure to capture errors from the new-aduser cmdlet and this seemed to work ok.
I have also considerd and tried using hte get-cssipdomin cmdlet first to check if the sip domain already exists, but I have a similar problem in that if you call get-cscsipdomain with a domain that doesn't exist it throws an error which I don't seem to be able to catch.
Any suggestions would be greatly appreciated.
TRY:
try
{
New-cssipdomain -id $SIPDomain -ERRORACTION SilentlyContinue
}
Maybe the command it self got a try/catch for errors.
You can perhaps have a look to this answer. It explains why try/catch is sometime not working.
Can't you just write :
$Res = New-cssipdomain -id $SIPDomain -ERRORACTION SilentlyContinue
And test the value of $Res ?
I guess the error you get is not a terminating error and that's why you can't catch it. Try to set the ErrorAction value to 'stop', that will make the error a terminating error and you'll be able to catch it in the catch block.