A study in Powershell scripting: Part 2

In this post I discuss about the  function I decided to incorporate into the script which is exporting Active Directory users to three sets of groups.

I like writing my own scripts because then I have complete control as to how it will work. Again going back to my principles I look at how it can be done manually and then transform them to code.

Manually I would have to collate all the Active Directory users in the master group by their last name and filter out A-H and so forth through the alphabet. So identifying some of the core cmdlets here is Get-ADGroupMember but in order to extract out the users is all about filtering, which generally means Where-Object (a little hint is that anything to do with whittling away records through the pipeline generally requires where-object, you will find that you use that 80% of the time in Powershell for day to day tasks ;))

The second part would involve regular expressions which I am absolutely terrible.

Second step. Look at help on Regular Expressions in Powershell. It is not a cmdlet but a concept so where to look? An easy way in the help is to type in keywords. Such as examples are like Get-Help *regular* and it will list down all the helpfiles relating to this.

Another tip is that all the conceptual ideas in Powershell  generally start with the word ‘about‘ and the spaces are replaced by an underscore. Following this syntax if I type Get-Help about_Regular_Expressions would give me the required helpfile. By the way if you wanted to list through ALL helpfiles type

Get-Help about*

This will show all the help files  for conceptual ideas in Powershell.

Anyway I am digressing. Back to the matter at hand, at this stage all I needed to do was to output a set of objects from the cmdlet. So I started to play with things like:

Get-Adgroupmember -identity GroupA

Then I hit across a problem. I needed to get the last name of every user but Get-Adgroupmember produces only a unique type and has a unique set of members in it. No surname or firstname properties.

A simple pipe through to Get-Member confirmed that the only members that seemed relevant to me would be samaccountname,and name. Then I remembered something reading Don Jones’s books and other various Powershell books out there said and that was I could pipe through the value of the object through to another one –providing– that they had the same property in each cmdlet! I thought to myself what other cmdlet produces Active Directory user information? Get-Aduser is something that comes to mind. If you look at Active Directory users even in the RSAT you can see that First Name and Last Name is there in the windows environment.

So I did a Get-Member on Get-aduser to confirm their existence. Sure enough there were givenname and surname were present as members which satisfied my requirements but it also has samaccountname….which is the glue that pieces the two together…which means I could do this:

Get-ADGroupMember -Identity "Domain Users" | Select -ExpandProperty samaccountname | Get-Aduser |Where-Object {$_.surname -like "Tan"}

The sequence essentially is:

  • get all members of group domain users.
  • Select the samaccountname property and transform it to text.
  • Pass along that the Get-aduser cmdlet and filter out the surname to be like Tan.

Now I needed to rather than find a single word I needed Powershell to match users based on their surname. So I changed the operator -like to -match. I needed to paramaterize certain values. Parameterizing the value for the user was easy, but I also wanted to parameterize the comparison operator but I came up with errors.


"Unexpected token '$regex' in expression or statement"

I did some digging around this but there was nothing much definitive so I asked for help at Powershell.org and the community was very helpful. (Thanks Dave Wyatt!).

The end result of my custom cmdlet is :

[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 1)]
$ADGroup,
[Parameter(Mandatory = $true,
Position = 2)]
[ValidateSet("givenname", "surname")]
$ADProperty,
[Parameter(
Position = 3)]
$Operator = 'match',
[Parameter(Mandatory = $true,
Position = 4)]
$regex
)
$a = get-adgroupmember -identity $ADGroup
$splatOperator = @{ $Operator = $True }
$a | Select -ExpandProperty samaccountname | Get-Aduser |
where $ADProperty @splatOperator $regex

}

In Part 3 I will discuss how I used this function to create the rest of the script and my thought process behind that.