Logging Error/Warning

I’m running an Invoke-Command which I have working as I want. In my test environment there is 1 computer that I turned off the ability to run commands against to log errors as I know production will have servers in all states.

I’ve attempted to use Try/Catch to grab the message I’m receiving (that it wont run against XYZ machine) but I cannot get it to spit anything out. I’d like for it to append a text document.

Below is a basic example of what I’m doing.

 

Input:

$Computers = (Get-ADComputer -Filter * -SearchBase "DC=Test,DC=Com").Name
$results = Foreach ($Computer in $Computers) {
Try {
Invoke-Command -ComputerName $computer -ScriptBlock {INSERT SOME COMMAND HERE 
} Catch {
$_.Exception | Out-File 'C:\Logs\Command-Errors.txt' -Append
}
}

$Results | Out-File 'C:\Logs\Command_Log.txt'
$Results | Export-CSV 'C:\Logs\Command_Log.csv'
$Results

 

Desired Result:

n Number of machines give me what I want and it is logged accordingly.

n Number of machines are offline/not allowing commands and it is logged accordingly.

 

Output:

[SERVER01] Connecting to remote server SERVER01 failed with the following error message : The client cannot connect to the destination specified in the request. Verify that the service on the destination is 
running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run 
the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig". For more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (SERVER01:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : CannotConnect,PSSessionStateBroken




Display Info That was Logged


Display Info That was Logged

Display Info That was Logged

 

Anyone have any idea how to catch that kind of message? I’ve tried it with $._Exception, $._Warning, and other variations I’ve found online. No luck.

 

Thanks in advance.

 

for try/catch to work, you need to turn the error into a terminating error as in

Try {
    Invoke-Command -ComputerName $computer -ErrorAction STOP -ScriptBlock {
        # INSERT SOME COMMAND HERE 
    }
} Catch {
    $_.Exception | Out-File 'C:\Logs\Command-Errors.txt' -Append
}

see Powershell ErrorAction | Sam's Corner

[quote quote=228181]for try/catch to work, you need to turn the error into a terminating error as in

PowerShell
8 lines
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59781px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
2
3
4
5
6
7
8
Try {
Invoke-Command -ComputerName $computer -ErrorAction STOP -ScriptBlock {
# INSERT SOME COMMAND HERE
}
} Catch {
$_.Exception | Out-File 'C:\Logs\Command-Errors.txt' -Append
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
see https://superwidgets.wordpress.com/2014/12/22/powershell-erroraction/

[/quote]

But say I’m scanning against 500 servers. I want it to keep running against all the servers it can connect to and run against then tell me which it had issues with, so I could rectify those issues.

Seeing as I’d rather not stop the command if possible so it can keep running, is there another method to capture the error message into a separate log/file then?

I guess, would this stop all the other Invoke’s or just the one it had an error on?

IMHO, storing anything in a text file (txt) for logging takes a huge amount of functionality away. If you do the following:

$Computers = (Get-ADComputer -Filter * -SearchBase "DC=Lombardi,DC=local").Name
$Path = 'HKLM:\System\CurrentControlSet\Control\CrashControl'
$Key1 = 'CrashDumpEnabled'
$Key2 = 'AlwaysKeepMemoryDump'
$Key3 = 'Overwrite'

$results = Foreach ($Computer in $Computers) {
    try {
        Invoke-Command -ComputerName $computer  -ErrorAction Stop -ScriptBlock {
            Get-ItemProperty -path $using:Path | 
            Select-Object -Property $using:Key1, $using:Key2, $using:Key3,@{Name='Status';Expression={'Success'}}
        }
    }
    catch {
        [pscustomobject]@{
            CrashDumpEnabled     = $null
            AlwaysKeepMemoryDump = $null
            Overwrite            = $null
            PSComputerName       = $Computer
            RunspaceId           = $null
            Status               = 'Failed: {0}' -f $_
        }
    }
}

$results

You take a good return and duplicate the object in your catch. Now you are returning the same object structure for success and fails. This can now be analyzed in Powershell or Excel using filters:

#Grouped results
$results | Group-Object -Property Status -NoElement
#What failed
$results | Where{$_.Status -ne 'Success'}

First off, this is the default behavior of this code

$results = Foreach ($Computer in $Computers) {
    Try {
        Invoke-Command -ComputerName $computer -ErrorAction STOP -ScriptBlock {
            # INSERT SOME COMMAND HERE 
        }
    } Catch {
        $_.Exception | Out-File 'C:\Logs\Command-Errors.txt' -Append
    }
}

In other words, this code, as is, will loop through the full list of $computers even if some error out in the middle.
Have you not tested the code before asking the question!!??

Second, read the blessed article posted. It specifically addresses this scenario, and I quote:

What if we want to process all files that do exist, yet be able to act individually on those that do not. One way to do that is to read data 
from the Error pipeline:

$Error.Clear()
Get-Item -Path .\iis1.txt,.\not-there1.txt,.\iis2.txt,.\not-there2.txt,.\iis3.txt
$MyErrors = @()
If ($Error) { 
    $Error | % {
        $Props = [ordered]@{
            Name = $_.CategoryInfo.TargetName
            Category = $_.CategoryInfo.Category
            Exception = $_.Exception | Out-String
        }
        $MyErrors += New-Object -TypeName PSObject -Property $Props
    }
}
$MyErrors | FT -Auto

In this example, I cleared the Error pipeline, ran the Get-Item cmdlet, then read through the Error records, extracted information I need and 
may want to act on, and saved them to members of $MyErrors array.

[quote quote=228229]IMHO, storing anything in a text file (txt) for logging takes a huge amount of functionality away. If you do the following:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
You take a good return and duplicate the object in your catch. Now you are returning the same object structure for success and fails. This can now be analyzed in Powershell or Excel using filters:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[/quote]

I’d swear you are following me now, correcting all the things, but I do appreciate it! :smiley:

I’ll play with it and wrap my head around it.

 

 

Sorrrrryyyyy. I was just asking before I began playing around with it as I had some other work items going on so I didn’t read too much into it yet.