2

I'm working with a wrapper script that calls a function which queries some databases inside specified servers and inserts metadata to a specific database on a separate server. I use the $error.count variable to determine if the script was successful or not. I anticipate some permission/extraction errors to happen and want these to be caught and ignored (no increase in the $error.count variable but having a warning written in the job log). I can confirm one permission error is happening and is being properly caught. The $error.count variable is not increased but a warning is printed from the catch showing the database that could not be accessed.

My problem occurs after the extraction/insertion function is finished running. Immediately after this function returns to the wrapper script, I have the $error.count variable print again. This time, it returns a 1 as if the error previously caught cascades into the wrapper script. As I mentioned previously, I do not want this to be included in the error count. I'm not sure how or why the $error.count is increased from this function.

Should I use a different variable to determine if the script "failed" or not? Is there some underlying reason why the $error.count would increase outside of the function that has the error while not increasing after the error is caught? Any guidance on this issue would be appreciated.

Code for reference: Wrapper function:

$errorCount = $error.count
    Write-Warning ("$errorCount Before function")
    Extraction/Insertion_Function -serverList $serverList -insertionDB $insertionDB -ErrorAction SilentlyContinue
    $errorCount = $error.count
    Write-Warning ("$errorCount After function")
    } catch {
    Write-Error "Error caught by wrapper: $_"
    }

Extraction/Insertion_Function:

ForEach ($db in $dbList) {
Write-Warning "$errorCount database
.
.
.
    try {
            $totalProperties = Get-ServerDBMetadata -DBConnectionString ($connStr) -DatabaseName $dbName -EA SilentlyContinue 
            } catch {
                Write-Warning "Unable to extract metadata from $dbname in $server"
                }
}

I then have the error count printing out inside the loop that extracts/inserts the metadata from each database to the insertion database, as well as in the loop for each server that contains the databases:

WARNING: 0 Before function
WARNING: 0 database
.
.
.
WARNING: 0 database
WARNING: Unable to extract metadata from *database* in *server*
WARNING: 0 database
.
.
.
WARNING: 0 database
**WARNING: 1 After function**

The error (permission issue) is caught inside the function but cascades to my wrapper script. I want this particular error to be ignored while NOT ignoring other, more serious errors (like being unable to connect to the server I'm inserting the metadata into) so placing -EA Ignore on the driver function inside the wrapper script is out of the question.

Kemilio
  • 88
  • 8
  • There isn't enough code here to determine what you're doing. Please provide a [mcve]. One thing you should know though, `$error.Count` is not a variable. `$error` is a (special) variable, and it is an array that contains all of the errors, so `$error.Count` is showing the size of the array. `$error` appends to the beginning, not the end, so `$error[0]` is always the latest error. If you want to know why the count is increasing, then look at `$error[0]` before and after the call, as the actual error will give you a clue as to what's going on. – briantist Jun 08 '17 at 16:39
  • I know whats going on. Its a permission issue. My problem is that I want to ignore that particular issue. As you can see by the error count being printed out, it is caught and isn't included in the error count inside the function where the error happens but is included outside the function in the wrapper script. I want to know why that is so I can figure out how to properly ignore it. Or, if a better "variable" for error handling can be used I would like to know what that is. – Kemilio Jun 08 '17 at 17:00

3 Answers3

2

Your primary problem with the try-catch not catching the error (even though you don't supply all of the code) is that your cmdlet explicitly calls -ErrorAction SilentlyContinue. Try/Catch blocks REQUIRE the use of terminating errors so in the case of your function/cmdlet, you need to change to -ErrorAction Stop for try/catch to appropriately handle an error from that function/cmdlet.

This needs to be updated for any other function/cmdlet in the code we can't see.

Edit described in comments below:

 $n = New-Object PSObject -property @{
    'Test1' = ''
    'Test2' = ''
    'Test3' = ''
}

try {
    get-process someprocess -ErrorAction Stop
    $n.Test1 = $true
} catch {
    $n.Test1 = $false
}

try {
    Get-WmiObject win32_computersystem -ErrorAction Stop
    $n.Test2 = $true
} catch {
    $n.Test2 = $false
}

try {
    Get-Content somefile.ext -ErrorAction Stop
    $n.Test3 = $true
} catch {
    $n.Test3 = $false
}


if ($n.Test1 -and $n.Test2 -and $n.Test3) {
    ## All procedures completed successfully -- do something magical
} else {
    ## At least one test procedure failed.
}
thepip3r
  • 2,855
  • 6
  • 32
  • 38
  • Do caught errors inside of functions still return as errors after the function is finished? It seems like the error inside of my Extraction/Insertion_Function is being caught, but when that function finishes and my wrapper continues its execution the error bubbles back up the stack as a non-terminating error. – Kemilio Jun 08 '17 at 17:45
  • It sounds like you're trying to create a kludgy error handling mechanism yourself to determine the success or failure of different parts of your code. If I have a process that relies upon a bunch of other processes being successful, I handle it in a way indicated in my edit above. Try/Catch your specific segment and instead of counting the $error variable, explicitly test for it (see above). – thepip3r Jun 16 '17 at 21:06
2

Replace SilentlyContinue with Ignore to ignore the error and not have it increase the count.

Extraction/Insertion_Function -serverList $serverList -insertionDB $insertionDB -ErrorAction Ignore

To catch it inside the function, use -ErrorAction Stop as in thepip3r's answer as try/catch statements only catch terminating errors.

G42
  • 9,791
  • 2
  • 19
  • 34
  • Even with ignore on the driver function in the wrapper script, the error count is still increased outside of the function. Besides, I wouldn't want the entire driver function to use -EA Ignore because there are potential problems I don't want ignored. – Kemilio Jun 08 '17 at 17:36
1

Logging the remaining errors since the last log:

While ($Global:ErrorCount -lt $Error.Count) {
    $Err = $Error[$Error.Count - ++$Global:ErrorCount]
    $ErrLine = "Error at $($Err.InvocationInfo.ScriptLineNumber),$($Err.InvocationInfo.OffsetInLine): $Err"
    Write-Host $ErrLine -ForegroundColor Red        # Log this
}
iRon
  • 20,463
  • 10
  • 53
  • 79