[Solved}Understanding use of PSCustomobject

This topic contains 14 replies, has 4 voices, and was last updated by  Joel Sallow 3 months, 2 weeks ago.

  • Author
    Posts
  • #97773

    Lev Leiderman
    Participant

    upate:

    $computers= "localhost"
    
      
      foreach ($pc in $computers){
      
            $test_connection = Test-Connection -ComputerName $pc -Count 1 -ErrorAction Continue
            $test_netconnection = Test-NetConnection $pc -Port 1433 -ErrorAction Continue
            
            #i had to delete these two lines and it make the script working, also, change the count to 1 in the upper variable
            #Test-Connection -ComputerName $pc -Count 3 -ErrorAction Continue
            #Test-NetConnection -ComputerName $pc -ErrorAction Continue
            [pscustomobject] @{
                               LocalPC             =$test_connection.PSComputerName;
                               Destination         =$test_connection.Remotecomputer
                              'Problematic-server'  =$test_connection.IPV4Address
                               Bytes               =$test_connection.Bytes
                               Time                =$test_connection.Time
                               MyLocalIP           =$test_netconnection.SourceAddress.IPv4Address
                               RemotePort          =$test_netconnection.RemoteAdress
                               ResolvedAddresses   =$test_netconnection.ResolvedAddresses
                               }
                                }
                                
  • #97776

    Axel Bøg Andersen
    Participant

    Hi Lev,

    I think you could simplify your code by only having one foreach loop:

    foreach ($pc in $Computers)
    {
        $tc=try{Test-Connection $pc -Count 1 -ErrorAction stop} catch {Write-Warning "$pc is not responding!"}
        if ($tc){
            $tn=Test-NetConnection $pc -Port 1433
            [pscustomobject]@{
                ComputerName = $tc.PSComputerName
                ProblematicServer=$tc.Address
                BufferSize=$tc.buffersize
                MyLocalIPAdress=$tn.SourceAddress
                RemoteAddress=$tn.RemoteAddress
                RemotePort=$tn.RemotePort
                TcpTestSucceeded=$tn.TcpTestSucceeded
            }
        }
    }
    

    Output is a PSObject for each machine you can contact. You can format the PSObject to any output you like. Furthermore you might want to experiment with formatting your code as an advanced function and let the PSObject be the output.

    • #97782

      Lev Leiderman
      Participant

      I did a foreach loop, but i did it twice, didn't thought about using it in your way
      i'm going to separate your code to understand better (and learn on the way 🙂

      this is all one variable, i didn't knew that you can declare a variable in that way
      (i'm in scripting a bit more than one month, so i'm learning each day something new through experience)

      $tc=try{Test-Connection $pc -Count 1 -ErrorAction stop} catch {Write-Warning "$pc is not responding!"}
      

      and here you've used Splatting

          if ($tc){
              $tn=Test-NetConnection $pc -Port 1433
              [pscustomobject]@{
                  ComputerName = $tc.PSComputerName
                  ProblematicServer=$tc.Address
                  BufferSize=$tc.buffersize
                  MyLocalIPAdress=$tn.SourceAddress
                  RemoteAddress=$tn.RemoteAddress
                  RemotePort=$tn.RemotePort
                  TcpTestSucceeded=$tn.TcpTestSucceeded
              }
          }
      }
      
      

      do i need to add "else" condition to the "IF" in order to get the error?

      one more quastion,
      if i'll take

      $tn=Test-NetConnection $pc -Port 1433

      i can't paste the code :\ it's allowing me only few lines

    • #97794

      Axel Bøg Andersen
      Participant

      You don't need an else section.

      If you want to pipe test-netconnection to Select-Object, you just remove $tn= from the beginning of the line.

    • #97797

      Lev Leiderman
      Participant

      and i do it like that:

      if ($tc){
                  [pscustomobject]@{
                  ComputerName = $tc.PSComputerName
                  ProblematicServer=$tc.Address
                  BufferSize=$tc.buffersize
                  MyLocalIPAdress=$tn.SourceAddress
                  RemoteAddress=$tn.RemoteAddress
                  RemotePort=$tn.RemotePort
                  TcpTestSucceeded=$tn.TcpTestSucceeded
              }
          }   Test-NetConnection $pc -Port 1433 |select-object
      }
      

      but if i remove the $tn variable, what will be used in the splatting table?
      i don't think that it'll work

      also i've noticed that you already used a custom property, and there is no need to make a new property

      this is a very interesting approach, it's as you said "i can make any output that i want" so actually i don't need to pipe it into select-object

    • #97824

      Axel Bøg Andersen
      Participant

      If you want to use Select-Object, you wouldn't use the splatting bit. Both techniques creates a new PS object.

      Often you would do something like:
      $obj = [PSCustomObject]@{...

      Then you can do:
      $obj | Formst-Table -autosize
      later

    • #97828

      Lev Leiderman
      Participant

      Ok, i will try to do it your way, i have to understand the logic in order to memorise this.

  • #97780

    Joel Sallow
    Participant

    In order for Try-Catch to trip, the error must be terminating. To ensure the error is terminating, you need to be using -ErrorAction Stop. Additionally, you'll need to put the Try-Catch inside the loop, not outside it; you'll probably get some very confusing behaviour doing it the way you've set it up.

    • #97786

      Lev Leiderman
      Participant

      The thing is that i have 3 servers and i don't want that it will stop if only one server is down
      that's why i've used -ea continue

      so i need to put the "catch" inside the "try" loop?

    • #97807

      Joel Sallow
      Participant

      -ErrorAction Stop will only halt the script if it is not caught with a catch{} block. An ErrorAction value of Stop turns all errors into terminating errors, but what happens when they're caught is still up to you — you can choose to log them and keep processing anyway, if that's what you want.

      If the code that raised the terminating error is within a try block, then the following catch code will execute, followed by one of two things:

      The code will continue from where it left off (default behaviour), or it will stop all actions in the present set and resume the script from the next set, if one exists (nonstandard). The latter behaviour has to be deliberately selected by specifying the break keyword in the catch block:

      # non terminating catch block
      foreach ($item in $things) {
          try {
              Test-Connection -ComputerName 'TotallyNotReal' -ErrorAction Stop
          }
          catch {
              $Errors += $_
              # this keyword isn't necessary, but it is perfectly allowable to explicitly define the action following the catch
              continue 
          }
      }
      
      #terminating catch block
      foreach ($item in $things) {
          try {
              Test-Connection -ComputerName 'TotallyNotReal' -ErrorAction Stop
          }
          catch {
              $Errors += $_
              # to select the terminating behaviour, the break keyword is necessary
              break
          }
      }

      Basically, all "-ErrorAction Stop" is doing for most purposes is ensuring you can catch it in the first place and let you do what you want with it. If you specify Continue instead, the catch block will never be able to trigger.

    • #97827

      Lev Leiderman
      Participant

      OK,
      i think i got it 🙂

      Acording to your code, i need to make one "try\catch" block with two Foreach statements One for Test-connection and one for Test-netconnection (both of them with either -ea "stop" or "continue")

    • #97858

      Joel Sallow
      Participant

      If you want the try-catch to function, don't use -ErrorAction Continue — it will prevent errors triggering the catch.

      As for two loops... eh, you could do one, and have the first error simply trip the catch and go right on ahead to the next loop iteration, wouldn't be a big deal, really. Basically as long as both commands are within the Try block, the first one to error out can make PS skip the rest, if that's what you want it to do (so if it fails the connection completely, it doesn't bother trying to do anything else with it).

      Also — why are you using both Test-Connection and Test-NetConnection? Their function is pretty similar, after all.

  • #97803

    David Schmidtberger
    Participant

    i think just a bit of commenting in here will help

    #loop through each computer within computers
    foreach ($pc in $Computers)
    {
    #$tc will contain the pc information if successfull, if pc is offline, $tc will be empty
        $tc=try{Test-Connection $pc -Count 1 -ErrorAction stop} catch {Write-Warning "$pc is not responding!"}
    #check contents of $tc, if empty do nothing, if has contents, test connection again to be able to splat information
        if ($tc){
            $tn=Test-NetConnection $pc -Port 1433
            [pscustomobject]@{
                ComputerName = $tc.PSComputerName
                ProblematicServer=$tc.Address
                BufferSize=$tc.buffersize
                MyLocalIPAdress=$tn.SourceAddress
                RemoteAddress=$tn.RemoteAddress
                RemotePort=$tn.RemotePort
                TcpTestSucceeded=$tn.TcpTestSucceeded
            }
        }
    }
    
    • #97831

      Lev Leiderman
      Participant

      Thanks alot David

      somthing that i don't understand,
      in your script you use the command

      $tn=Test-NetConnection $pc -Port 1433

      before the splatting.

      update:i've updated the post name and the first post to

  • #97848

    David Schmidtberger
    Participant

    Well, Axel's code will provide you with a pscustom object with the data as presented.
    It is up to you to do something with that object's data. Just make sure you do it within the foreach loop or you lose the data when it connects to the next machine.

    As far as the splatting, you are basically building the same types of objects. It is just a question of what you do with the object once created.

    Neither approach is really "wrong"

You must be logged in to reply to this topic.