Diff between creating custom object using AddMember and Hashtable

This topic contains 5 replies, has 3 voices, and was last updated by Profile photo of Sikander Mirza Sikander Mirza 3 months, 1 week ago.

  • Author
    Posts
  • #55148
    Profile photo of Sikander Mirza
    Sikander Mirza
    Participant

    Hi,

    I am learning scripting, i came across a script which Creates OU's in Active Directory
    Using an Inputfile and produces an Csv log output.

    I have this function log-me in Example 1, i have re-written it Example 2 in the style i learned [i am following MVA/DonJones/JasonHelmic video tuts].

    My question is, why do many people who write scripts for automation use Example 1 method, creating an object, adding members,
    where as it could be done in hashtable format as in example 2.

    Is it an old v1 or v2 style of writing or does it have any advantages over an hashtable?
    because i noticed that we cannot have 2 NoteProperties with same name, same with hashtable, we cannot have two keys with same name.

    What are the advantages/pro's con's of these two styles.

    #Example 1
    Function Log-Me{
    
    param(
    	[String]$OUPathTrans,
    	[Boolean]$validate,
    	[String]$OUStatus,
    	[String]$ParOUPath
    )
    
        $object = New-Object -TypeName psobject
    
        $object | Add-Member -Name Complete_OU_DN -MemberType NoteProperty -Value $OUPathTrans
        $object | Add-Member -Name Parent_OU_DN -MemberType NoteProperty -Value $ParOUPath
        $object | Add-Member -Name AlreadyExists -MemberType NoteProperty -Value $validate
        $object | Add-Member -Name OUCreated -MemberType NoteProperty -Value $OUStatus
        $object | Add-Member -Name Parent_OU_DN1 -MemberType NoteProperty -Value $ParOUPath
    
    
        return $object
    }
    
    
    #Example2
    Function Log-Me{
    
    param(
    	[String]$OUPathTrans,
    	[Boolean]$validate,
    	[String]$OUStatus,
    	[String]$ParOUPath
    )
    
    
        $object = [PSCustomObject][ordered]@{'Complete_OU_DN' = $OUPathTrans;
                                    'Parent_OU_DN' = $ParOUPath;
                                    'AlreadyExists' = $validate;
                                    'OUCreated' = $OUStatus;
                                
        }
    
        $object
    }
    
    • This topic was modified 3 months, 1 week ago by Profile photo of Sikander Mirza Sikander Mirza. Reason: spell
  • #55151
    Profile photo of Sikander Mirza
    Sikander Mirza
    Participant

    One more thing i noticed, an empty array is declared at the beginning of the script eg: $collobjects = @()
    and the log-me function the values is assigned to this array eg: $collobjects += log-me –

    and finally the array is exported to an csv, so if we use hashtable in the log-me function will it still work.
    Please don't go on the code specific, i need the concept.

  • #55152
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    There are many ways to accomplish the same things in scripting. The pscustomobject class was introduced in V3, so if you want your code to function in v2, you need to use older methods to generate objects. You can still use hash tables to generate a PSObject to be supported in V2+, however, performing ordering is more complicated:

    $props = @{
        'Complete_OU_DN' = $OUPathTrans;
        'Parent_OU_DN' = $ParOUPath;
        'AlreadyExists' = $validate;
        'OUCreated' = $OUStatus;
    }
    
    New-Object -TypeName PSObject -Property $props
    

    One of most overlooked methods for generating object is Select-Object.

    $os = Get-WMIObject -Class Win32_OperatingSystem
    $cs = Get-WMIObject -Class Win32_ComputerSystem
    
    
    # We'll use Select-Object to generate a new PSObject and we
    # can even rename the Manufacturer from Win32_ComputerSystem so
    # that there is not duplicated property names
    $myNewObject = $os |
    Select Manufacturer, 
           SerialNumber, 
           SystemDirectory,
           @{Name="ComputerManufacturer";Expression={$cs.Manufacturer}}
    

    Personally, I don't like Add-Member to create objects. It's not very clean and when you start looping you have to use -Force to overwrite property names. Add-Member can be used to add the same value to each row, for instance you want to add ComputerName to the previous object:

    $myNewObject | Add-Member -MemberType NoteProperty -Name ComputerName -Value $env:COMPUTERNAME
    

    Add-Member can do some other advanced items like setting default viewable properties: https://learn-powershell.net/2013/08/03/quick-hits-set-the-default-property-display-in-powershell-on-custom-objects/

  • #55153
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    Your second question about defining an empty array. A PSObject is an array of hash tables. You will see examples like this:

    $object = @()
    
    for ($i=1;$i -le 5;$i++) {
       $object += New-Object -TypeName PSObject -Property @{ComputerName = ("Computer{0}" -f $i)}
    }
    
    $object
    

    Before you run it, remark out the first line. When you do, you should receive an error "does not contain a method named 'op_Addition'". Un-remark it and run it again. The first time it was run, without defining an array, you're trying to append (add) to a static object, so there is nothing to add to. Here is a the best method I have found to append to an object:

    $object = for ($i=1;$i -le 5;$i++) {
       New-Object -TypeName PSObject -Property @{ComputerName = ("Computer{0}" -f $i)}
    }
    
    $object
    
  • #55154
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    Add-Member was the only way to populate an object in the early versions of PowerShell. You still see a lot of scripts using Add-Member because they were either written a long time back, the author isn't aware of any other approach or they haven't kept up to date with changes in PowerShell

    Using a hash table is a lot less work and is the recommended approach.

  • #55231
    Profile photo of Sikander Mirza
    Sikander Mirza
    Participant

    Thanks, its clear now.

You must be logged in to reply to this topic.