2

I am working on a script which will do the following:

  1. Check if a service (in this case XboxGipSvc) is running
  2. If service is running, do nothing
  3. If service is not running, attempt to start service
  4. If service fails to start, catch error and log to C:\TEMP\RemediationLog.log

I believe I have done my try/catch block correctly, however even though im getting errors when I run the try block, it does not log $error to the file as expected.

Heres my code:

$Error.Clear()

try{
    $Airlock1 = Get-Service -Name XboxGipSvc -ErrorAction Stop
        while ($Airlock1.Status -ne "Running"){
                                                                Start-Service $Airlock1 -ErrorAction Stop
                                                                Write-Host $Airlock1.Status
                                                                Write-Host "Service is Starting"
                                                                Start-Sleep -Seconds 5
                                                                $Airlock1.Refresh()
                                                                if ($Airlock1.Status -eq "Running"){Write-Host "Service is now running"}
                                                            }
   }
catch [Microsoft.PowerShell.Commands.StartServiceCommand]{
                                                                {     
                                                                    if ($error -ne $null)
                                                                        {
                                                                            $test = Test-Path -path C:\TEMP\RemediationLog.log
                                                                            if ($test -eq $false){New-Item -Path C:\TEMP\RemediationLog.log}
                                                                            $error | Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append
                                                                            Write-Host $error.Exception[0]
                                                                        }
                                                                }
                                                         }
Tee1998
  • 23
  • 5
  • A couple observations. I believe your catch should be for exception type `[Microsoft.PowerShell.Commands.ServiceCommandException]`. `if ($error -ne $null)` should be reversed to `if ($null -ne $error)` or just `if ($error)` however this if statement is unneeded altogether since we know there is an error as we are in a catch block afterall. – Daniel Aug 18 '22 at 05:02
  • Thanks for the helpful comment! I now realize that the if statement was something I had leftover from a previous version of the same script before I realized using try/catch would be better. Don't know why it didnt strike me as something redundant. – Tee1998 Aug 22 '22 at 01:33

2 Answers2

2

In addition to @Daniel's helpful comment:

Using multiple catch statements

A try statement can have any number of catch blocks. For example, your script has a try block that checks the $Airlock1.Status has only a [Microsoft.PowerShell.Commands.StartServiceCommand] catch block but might simply fail on an different error and therefore might need a general catch block:

try {
    ...
}
catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
    ...
}
catch {
    Throw "An unexpected error occurred that isn't logged: $_"
}

Accessing exception information

Within a catch block, the current error can be accessed using $_, which is also known as $PSItem. The object is of type ErrorRecord.

$Error

$Error in an automated variable which contains an array of error objects that represent the most recent errors. The most recent error is the first error object in the array $Error[0].

Meaning that you probably just want to use the current item ($_) in the Catch block and format all the error information to a single line. Something like:

$ErrorMessage = '{0} at {1}:{2} char: {3}' -f
    $_.exception.Message,
    $_.InvocationInfo.ScriptName,
    $_.InvocationInfo.ScriptLineNumber,
    $_.InvocationInfo.OffsetInLine
$ErrorMessage |Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append

(note that this is quiet similar to how the newer PowerShell (Core) versions format an ErrorRecord output)

For what you tried

"It does not log $error to the file as expected'
What do you expect and what is the actually output you experience?
Note that the output might differ depending on the PowerShell version, but should be similar to what is shown when you just type $Error at the PowerShell prompt.

But if you really intended to list all the errors since the $Error.Clear, you might do something like this:

$Error |ForEach-Object {
    '{0} at {1}:{2} char: {3}' -f
        $_.exception.Message,
        $_.InvocationInfo.ScriptName,
        $_.InvocationInfo.ScriptLineNumber,
        $_.InvocationInfo.OffsetInLine
} |Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append
iRon
  • 20,463
  • 10
  • 53
  • 79
  • Hi there, for what I tried, the expected output is essentially the content of $error. When I ran the script however, it was just nothing. No content, it did not output anything at all. I am going to try your solution and see how I go – Tee1998 Aug 22 '22 at 01:38
  • Hi there, I have attempted to implement your code block for pushing the file out to RemediationLog.log and it still does not appear to be working. Please advise? https://pastebin.com/raw/NwDWUbBD – Tee1998 Aug 22 '22 at 03:48
  • "*does not appear to be working*" isn't much to advise upon... Please elaborate. E.g. does the second `Catch` return anything? – iRon Aug 22 '22 at 06:33
  • I found this Blog it might help: https://community.spiceworks.com/topic/1404275-try-catch-not-working?page=1#entry-5432576 , I updated my answer. – Mike Kennedy Aug 22 '22 at 15:32
  • Apologies for the vagueness. I am catching errors in Catch Block 2 however no errors are being output to the Remediation Log – Tee1998 Aug 23 '22 at 00:13
  • What Code are you using? – Mike Kennedy Aug 23 '22 at 14:23
  • "*I am catching errors in Catch Block 2 however no errors are being output to the Remediation Log*" those is because the errors are apparently no `[Microsoft.PowerShell.Commands.ServiceCommandException]` exceptions and possibly even prevent these specific exceptions from being raised. You might want to change the `Throw "An unexpected error occurred that isn't logged: $_"` to a non-terminating error: `Write-Error "An unexpected error occurred that isn't logged: $_"` – iRon Aug 23 '22 at 14:52
  • Seems to be resolved now, thank you for your assistance – Tee1998 Aug 24 '22 at 06:37
0

Try something like this:

$Error.Clear()

try{
    $Airlock1 = Get-Service -Name XboxGipSvc -ErrorAction Stop
        while ($Airlock1.Status -ne "Running"){
            Start-Service $Airlock1 -ErrorAction Stop
            
            Write-Host $Airlock1.Status
            Write-Host "Service is Starting"
            Start-Sleep -Seconds 5
            $Airlock1.Refresh()
        If ($Airlock1.Status -eq "Running"){Write-Host "Service is now running"}
                                                            }
}
catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
        If ($error){
            If (Test-Path -Path C:\TEMP\RemediationLog.log ) {
                $error | Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append
                Write-Host $error.Exception[0] -ForegroundColor Green
            }
            Else {
                New-Item -Path C:\TEMP\RemediationLog.log
                $error | Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append
                Write-Host $error.Exception[0] -ForegroundColor Yellow
            }
        }
}

If I add iRon

$Error.Clear()

try{
    $Airlock1 = Get-Service -Name XboxGipSvc -ErrorAction Stop
        while ($Airlock1.Status -ne "Running"){
            Start-Service $Airlock1 -ErrorAction Stop
            Write-Host $Airlock1.Status
            Write-Host "Service is Starting"
            Start-Sleep -Seconds 5
            $Airlock1.Refresh()
        If ($Airlock1.Status -eq "Running"){Write-Host "Service is now running"}
                                                            }
}
catch [Microsoft.PowerShell.Commands.ServiceCommandException]{
    If ($error){
        If (Test-Path -Path C:\TEMP\RemediationLog.log ) {
                $Error |ForEach-Object {
                '{0} at {1}:{2} char: {3}' -f
                $_.exception.Message,
                $_.InvocationInfo.ScriptName,
                $_.InvocationInfo.ScriptLineNumber,
                $_.InvocationInfo.OffsetInLine
            } |Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append
            Write-Host $Error -ForegroundColor Green
        }
            Else {
                $Error |ForEach-Object {
                '{0} at {1}:{2} char: {3}' -f
                $_.exception.Message,
                $_.InvocationInfo.ScriptName,
                $_.InvocationInfo.ScriptLineNumber,
                $_.InvocationInfo.OffsetInLine
            } |Out-File -FilePath C:\TEMP\RemediationLog.log -Force -Append
        }
    }
}

The output would be:

Service 'Xbox Accessory Management Service (XboxGipSvc)' cannot be started due to the following error: Cannot start service XboxGipSvc on computer '.'. at :6 char: 13
Mike Kennedy
  • 374
  • 2
  • 6