Let me be clear on this one: Select
is bad, Add-Member
is good. 😉
OK, OK, this is not a one-size-fits-all answer, and there are plenty of scenarios in which Select-Object
is useful, but in a lot of cases it is being misused. The most frequent one, when someone tries to use Select-Object
or Format-Table
to add a new attribute to the displayed objects. In that particular scenario these two cmdlets basically create one-time-use disposable objects for a quick output, while Add-Member
adds an additional property and preserves the original objects for subsequent use.
A quick example, let’s say you want to see the Primary Group for your AD users. Primary group can be calculated by merging account domain SID and primary group ID so you probably end up with something like:
$PrimaryGroup = Get-QADGroup “$($user.Sid.AccountDomainSid)-$($user.PrimaryGroupId)“
Now, to add a column to the user output you could use Select-Object
or Format-Table
and supply the additional value using a hash-table parameter:
Get-QADUser | Select Name, @{Name=“PrimaryGroup“;Expression={(Get-QADGroup “$($_.Sid.AccountDomainSid)-$($_.PrimaryGroupId)“).Name}}
Get-QADUser | Format-Table Name, @{Label=“PrimaryGroup“;Expression={(Get-QADGroup “$($_.Sid.AccountDomainSid)-$($_.PrimaryGroupId)“).Name}}
(Note a small gotcha by the way: the column name is Name for Select-Object
but Label for Format-Table
;))
However, both of these operations have a very important side effect – they kill the original objects and create new disposable ones instead. The collection you get is basically just a formatting thing which you can no longer use in other operations (e.g. pipe to yet another cmdlet).
For example if I use the Select code above in a PowerGUI script node I will indeed get the output in the grid, however, if you pay close attention (click the image to see the detail) you will see that I cannot add any other columns to the grid (and see for example users’ phone numbers), and the Actions pane to your right is empty – the usual actions for user objects are not there. 😦
Enter Add-Member
. This cmdlet is a complete opposite to Select
and Format-*
– it adds a new member to the objects while preserving all other properties and the object type.
So if instead of the code above we use something like:
Get-QADUser | Add-Member -Name “PrimaryGroup“ -Value {(Get-QADGroup “$($this.Sid.AccountDomainSid)-$($this.PrimaryGroupId)“).Name} -MemberType ScriptProperty -Force -PassThru
We get a nice set of objects with all user properties there and the new one added. As a result, inside PowerGUI admin console you see this new column, but can still add any other columns and perform any usual actions – check out the right-hand pane!
Tags: AD, AD cmdlets, Active Directory, Examples, KB, Knowledge Base, Known Issues, PowerGUI, PowerShell
Select is bad, Add-Member is good – to my mind they fulfil two different roles.
Add-Member is when you want to do further processing as you show
Select & calculated field when only want to display.
Lots of times I only want to display so use select or format
Good example of using Add-Member though
Yep:
* Select is a quick and dirty way to get the values.
* Add-Member if you want the thing to be further re-usable.
The problem is that today most examples in the blogs/forums/etc. use Select, and people start looking at it as a universal solution, which it is not.
I’m a huge proponent of the bad form of Select-Object. 🙂 As such let me say that every time I use it, it’s because I either do not care what the original object was, or I actively did not want the original object.
Even in cases when I _should_ do a script using add-member, I will usually shy away from doing so. Why? I find the steps required to create a custom object very tedious and lacking in clarity of the written code.
This is why I submitted a connect feature suggestion to MSFT to ask them to make the creation of a custom object with a large set of properties easier to do by expanding the syntax of add-member and/or new-object.
Please check out the suggestion here and vote for it if you agree, or leave comments there to ensure that MSFT sees the discussion.
https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=355131&SiteID=99
I guess my reply from a few days ago got lost in the ether. I’m a big proponent of using Select-Object to construct synthetic objects. I understand your point, however in my own usage it is much more common that I don’t need or don’t want the rest of an original object. In many cases, there *was* no original object. In these cases, Add-Member provides the exact same end result as Select-Object.
Even outside of these cases, I find the Add-Member cmdlet very awkward to the point that I created a Connect bug to address usability issues.
Found and despammed your comment. Will go and vote for the submission at the connect site (which I hope others will do as well) – this cmdlet is indeed very hard to use.
Thanks for the post. I am trying to learn to think “on the next level” and this kind of writing helps me get my head around some different ways of looking at my scripts. I added on Twitter that a series of posts exploring the various ways in which Add-Member could be used would be very helpful to those still learning the language like myself.