I am trying to detect if a database connection succeeded, and if so, do work, otherwise,report the connection error and obviously bypass the DB tasks.
I'm embarrassed that I seem to be failing Syntax 101.
I've tried two different approaches, neither which works.
Approach 1
In this code, I can't seem to get the $connection.State = Open syntax correct. I can see in the debugger $connection.State = Open -- i just can't seem to test for it properly.
$connection = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($conninfo)
Try {$connection.open()}
Catch {Write-Warning "Sorry, DB Connect failed"}
If ($connection.State = Open) {
Write-Output "No Error"
DoWork()
$connection.Close()
}
Approach 2:
In this code, connection errors are caught, but successful connections do not enter the expect "No error block".
$connection = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($conninfo)
Try {$connection.open()}
Catch {Write-Warning "Sorry, DB Connect failed"}
If (!$error) {
Write-Output "No Error"
DoWork()
$connection.Close()
}
}
Try{}Catch{} only hit terminating errors. Try something like:
Try
{
$erroraction = "stop"
$connection.open()
$erroraction = "continue"
}
Catch {
Write-Warning "Sorry, DB Connect failed"
}
of use non-terminating error handling
$connection.open()
if(!$?) #did the last command fail?
{
Write-Warning "Sorry, DB Connect failed"
}
edit: I may have misunderstood the exact question, but if the problem is that $? is incorrectly true on an error, its because it uses only the last command. So your catch block running write-warning is successful, you'll need to store the $? value immediately after the command you expect to fail or set a bool in the catch block directly to trigger your next block.
OK, although it doesn't answer all my questions, here is working code:
try {
$connection.Open()
Write-Debug "No Error"
doStuffHere()
}
Catch {Write-Warning "Sorry, DB Connect failed"}
My failure was not remembering any error occurring inside the try block results in immediately exiting the try block and going to the catch. (Actually, its one of those things I forgot I knew -- I had to be reminded.)
Aside from that though, I'd still like to determine the correct way to test Connection.State to see if the connection is open or closed. Probably need to open another question.
Related
I have a PowerShell script that need to check if there is internet connectivity before running the rest of the script. For the example using Test-Connection
if (Test-Connection example.com) {
Write-Host "Connection available"
# do-other things
} else {
Write-Host "No internet connection"
Exit
}
The problem with this approach is if there is no connection it gives this error message:
Testing connection to computer 'example.com' failed: Cannot resolve the | target name. and then the actual message follows No internet connection but the idea was to have it move to the else clause not giving that error message when there no connection.
For example when there is no internet connection the error message No internet connection is printed, that's it, nothing else. How can I achieve this.
Test-Connection doesn't seem to have something that we can catch with try-catch, but there is a -Quiet parameter that may do what you want. It translates the output to a simple boolean.
Testing without and with an internet connection:
Per #mukunda's answer, Test-Connection has a -Quiet switch that ignores errors and returns a boolean result - see the documentation for Test-Connection for the details.
Note there's some perhaps unexpected behaviour if you're testing multiple sites in a single call:
If any ping to a given target succeeds, $True is returned
In other words, even if some sites fail you'd still get $true returned.
Note that in general you can also suppress errors in cmdlets with -ErrorAction "SilentlyContinue", and check the return value after:
$result = Test-Connection -Ping "www.example.org" -ErrorAction "SilentlyContinue";
if ($null -eq $result)
{
Write-Host "No internet connection"
Exit
}
else
{
Write-Host "Connection available"
# do-other things
}
This question already has answers here:
PowerShell - Why "Divide By Zero Exception" is not being Caught?
(3 answers)
Closed 8 years ago.
When I put this snippet into powershell v2.0 on one of my machines
try{
$test = 1/0
write-host "not terminating"
}
Catch{
write-host "caught"
}
write-host "continuing"
the error terminates the script and doesn't catch it and doesn't continue. I get the cannot divide by zero error.
Cannot divide by zero exception message
But in my v4.0 i get this output
caught
continuing
when I put that into my v4.0 powershell it catches the terminating error and it continues. Whats the deal, is this a v2.0 specific issue? How do I get the script to continue in powershell v2.0 and catch the error?
Try adding $ErrorActionPreference = "Stop" in your try block. This will turn all errors in to terminating errors. There might be a problem between v2 and v4 of powershell, where v4 defines an error as terminating, but v2 does not. Try/catch statements only work on terminating errors.
If that doesnt work, try writing something like:
try {
$test = 1/0
if($?) {
write-host "not terminating"
}
else {
$errors[0].Exception
}
}
$? is an automatic variable that stores information whether the last operation completed successfully or not.
I have the following code which I thought would allow me to catch an error and instead of generating the error write out "An Error Occurred".
Unfortunately, it still shows the error "Failed to restart the computer: Access is denied" instead.
I know why this is happening but I want to be able to catch the error and reformat it. What am I doing wrong?
try {
Restart-Computer -ComputerName MFG-KY-PC74 -Force
} catch {
Write-Host "An Error Occurred"
}
In PowerShell there are terminating and non-terminating errors. The former terminate script execution (if not caught) and can be caught by try..catch, the latter don't terminate script execution (so there's nothing to catch). The error you're receiving is a non-terminating one, so you need to make it a terminating error by appending -ErrorAction Stop to the statement:
try {
Restart-Computer -ComputerName MFG-KY-PC74 -Force -ErrorAction Stop
} catch {
write-host "An Error Occurred"
}
Alternatively you can set $ErrorActionPreference = "Stop" if you want all errors to become terminating errors.
See this article on the Scripting Guy blog for more information.
I have script that creates user accounts and establishes an e-mail address for those accounts. All 'create-commands' are surrounded by a try/catch block to catch errors and add a message to the output log. This works fine... except for the enable-mailbox command
try {
Enable-Maibox (.. parameters ...)
}
catch {
$errorsEncountered = $true
Write-Output "Error establishing e-mail address for $($UserData.username)"
}
when the enable-mailbox command fails... the catch-part is skipped. Why is this? And how can I fix this?
Non-termineting errors are not catched. Use '-ErrorAction Stop' to make the errors terminating errors.
Enable-Maibox (.. parameters ...) -ErrorAction Stop
I could be wrong but "Enable-Maibox" looks mis-spelled.
I am having problems catching an error in PowerShell when a connection fails to a SQL Server using Invoke-Sqlcmd. This is some generic code to demonstrate the issue:
CLS
$server = "Localhost\fake"
try
{
Invoke-Sqlcmd -Query "SELECT DB_NAME() as [Database]" -Server $server
}
catch
{
Write-Host "Error connecting to server " $server
}
I get the following error:
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name
is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
I was expecting to get the one line statement: "Error connecting to server Localhost\fake"
It would appear that error is considered non-terminating which is a bit odd. Try the Invoke-SqlCommand with an additional parameter: -ErrorAction Stop. If there error is non-terminating, this will convert it to a terminating error that you can catch.
Posting additional info to supplement the answer by #KeithHill as an answer since it is too long for a comment.
If the error record was created by the Write-Error commandlet it is non-terminating and subject to the behavior specified by the -ErrorAction argument or the $ErrorActionPreference system variable. Errors using throw are terminating. See the documentation for Write-Error (Note that PowerShell 4.0 and below do not have the -Exception parameter mentioned in the web page.) and about_Throw in the PowerShell help system.
If you want to add custom error information and make it a terminating error, throw from your catch block as follows:
catch
{
throw (New-Object System.Exception "Error connecting to server $($server).", $_.Exception)
}
You can use Write-Error if you want termination to behave as specified by the -ErrorAction argument. In PowerShell 4.0 and below the Write-Error commandlet does not allow a -Exception argument and therefore will not provide an InnerException. That means that the caller would have to examine the collection in the $Error system variable if it needs to determine the original exception. In later versions you can Use Write-Error -Message "Some additional error information." -Exception $_.Exception in your catch block.
Try
CLS
$server = "Localhost/fake"
try
{
Invoke-Sqlcmd -Query "SELECT DB_NAME() as [Database]" -Server $server
}
catch
{
$_ | Out-Null
Write-Host "Error connecting to server " $server
}
This will capture the error and redirect it to null and display your write-host