I am working on a script which will do the following:
- Check if a service (in this case XboxGipSvc) is running
- If service is running, do nothing
- If service is not running, attempt to start service
- 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]
}
}
}
CodePudding user response:
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 typeErrorRecord
.
$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
CodePudding user response:
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 {
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 {
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