PowerShell Trick via @alanrenouf

Alan Renouf gave a vBrownBag presentation on Advanced PowerCLI 5.5R2 last night. During the show, he showed an interesting bit of code:

$output = "" | Select VmName, PgName
$output.VmName = "value1"
$output.PgName = "value2"

This was intriguing to me. The “proper” way to create an object with attributes is to use New-Object and pipeline it through some Add-Member commands.

$output = New-Object PSObject |
Add-Member -PassThru NoteProperty VmName "value1" |
Add-Member -PassThru NoteProperty PgName "value2"

That creates an excessive, and somewhat unreadable, pipeline for objects with a long list of members, especially if a member’s name is long. It’s a pretty neat trick to make your code look pretty neat.

In fact, I had just added a function with such a list to my powercli-modules repo and was aggravated that I couldn’t make it look any more elegant, so I converted it from the New-Object | Add-Member style to the $object = “” | Select Attribs style. Here’s the diff:

-                New-Object PSObject |
-                Add-Member -PassThru NoteProperty "VMhost"                   $VMHost.Name                                |
-                Add-Member -PassThru NoteProperty "Model"                    $VMHostModel                                |
-                Add-Member -PassThru NoteProperty "Sockets"                  $VMHostView.Hardware.cpuinfo.NumCPUPackages |
-                Add-Member -PassThru NoteProperty "Cores"                    $VMHostView.Hardware.cpuinfo.NumCPUCores    |
-                Add-Member -PassThru NoteProperty "Threads"                  $VMHostView.Hardware.cpuinfo.NumCPUThreads  |
-                Add-Member -PassThru NoteProperty "VMs"                      $VMCount                                    |
-                Add-Member -PassThru NoteProperty "vCPU"                     $CPUCount                                   |
-                Add-Member -PassThru NoteProperty "vCPU/Core"                $vCPUPerCore                                |
-                Add-Member -PassThru NoteProperty "RAM (GB)"                 $RAMGB                                      |
-                Add-Member -PassThru NoteProperty "RAM Usage (GB)"           $RAMUsageGB                                 |
-                Add-Member -PassThru NoteProperty "RAM Free (GB)"            $RAMFreeGB                                  |
-                Add-Member -PassThru NoteProperty "RAM Usage (%)"            $PercentRAMused                             |
-                Add-Member -PassThru NoteProperty "15% RAM Reservation (GB)" $RAMreservedFree                            |
-                Add-Member -PassThru NoteProperty "Available RAM (GB)"       $RAMavailable
+                $VMHostInfo = "" | Select VMhost, Model, Sockets, Cores, Threads, VMs, vCPU, vCPU/Code, "RAM (GB)", "RAM Usage (GB)",
+                                          "RAM Free (GB)", "RAM Usage (%)", "15% RAM Reservation (GB)", "Available RAM (GB)"
+                $VMHostInfo.VMhost = $VMHost.Name
+                $VMHostInfo.Model  = $VMhostModel
+                $VMHostInfo.Sockets = $VMHostView.Hardware.cpuinfo.NumCPUPackages
+                $VMHostInfo.Cores = $VMHostView.Hardware.cpuinfo.NumCPUCores
+                $VMHostInfo.Threads = $VMHostView.Hardware.cpuinfo.NumCPUThreads
+                $VMHostInfo.VMs = $VMCount
+                $VMHostInfo.vCPU = $CPUCount
+                $VMHostInfo.'vCPU/Code' = $vCPUPerCore
+                $VMHostInfo.'RAM (GB)' = $RAMGB
+                $VMHostInfo.'RAM Usage (GB)' = $RAMUsageGB
+                $VMHostInfo.'RAM Free (GB)' = $RAMFreeGB
+                $VMHostInfo.'Ram Usage (%)' = $PercentRAMused
+                $VMHostInfo.'15% RAM Reservation (GB)' = $RAMreservedFree
+                $VMHostInfo.'Available RAM (GB)' = $RAMavailable
+                $VMHostInfo

Note that when not assigning New-Object and the pipeline to a variable, as above, the new object is then displayed to the screen (or pushed into the pipeline, etc.). Our little trick doesn’t ever do this because we are assigning to a variable, so we throw out the variable by itself on a line to display the object for equivalent effect. Obviously, you may not need that in every situation, so pay attention to what you’re doing.

= “” | select VmName .VmName =…

Leave a comment