Logging Error/Warning

Welcome Forums General PowerShell Q&A Logging Error/Warning

Viewing 6 reply threads
  • Author
    Posts
    • #228172
      Participant
      Topics: 2
      Replies: 8
      Points: 59
      Rank: Member

      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.

       

    • #228181
      Participant
      Topics: 12
      Replies: 524
      Points: 1,220
      Helping Hand
      Rank: Community Hero

      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 https://superwidgets.wordpress.com/2014/12/22/powershell-erroraction/

    • #228220
      Participant
      Topics: 2
      Replies: 8
      Points: 59
      Rank: Member

      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/

      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?

      • This reply was modified 2 weeks, 5 days ago by ALombardi01.
    • #228229
      Participant
      Topics: 12
      Replies: 1623
      Points: 2,565
      Helping Hand
      Rank: Community Hero

      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'}
      
      • This reply was modified 2 weeks, 5 days ago by Rob Simmers.
    • #228238
      Participant
      Topics: 12
      Replies: 524
      Points: 1,220
      Helping Hand
      Rank: Community Hero

      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.

      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.
      
      • This reply was modified 2 weeks, 5 days ago by Sam Boutros.
      • This reply was modified 2 weeks, 5 days ago by Sam Boutros.
    • #228265
      Participant
      Topics: 2
      Replies: 8
      Points: 59
      Rank: Member

      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

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

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

       

       

    • #228268
      Participant
      Topics: 2
      Replies: 8
      Points: 59
      Rank: Member

      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.

      First off, this is the default behavior of this code

      PowerShell
      10 lines

      <textarea class=”ace_text-input” style=”opacity: 0; height: 18px; width: 6.59781px; left: 51px; top: 0px;” spellcheck=”false” wrap=”off”></textarea>

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      $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
      }
      }
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

      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:

      PowerShell
      21 lines

      <textarea class=”ace_text-input” style=”opacity: 0; height: 18px; width: 6.59781px; left: 51px; top: 0px;” spellcheck=”false” wrap=”off”></textarea>

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      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.
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

      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.

Viewing 6 reply threads
  • You must be logged in to reply to this topic.