Splatting - over complex?

I’m trying to tidy up a script for production and I’d like feeding if the following is over complicating the use of splatting? The original example came from Mike Robbins - 2013 PowerShell Scripting Games Advanced Event 4 – Auditors Love Greenbar Paper · Mike F. Robbins


$LDAPGroupFilter = "(&(objectcategory=group)(objectclass=group)(mailNickname=*)(!mail=*@internal.com)(!cn=zzz*)(!cn=l-*)(!cn=g-*))"

$UserParameters = @{
	Filter = 	    $LDAPGroupFilter
	Properties = 'GivenName',
	             'surname',
	             'cn',
	             'mail',
	             'proxyAddresses'
	ErrorAction = 'Stop'
	ErrorVariable = 'ADIssueGroup'
}

$Group = Get-ADGroup @Params 
$Params.Property = $Params.Properties  
$Params.Remove("Properties")     
$Params.Remove("Filter")       
$Group | Select-Object @Params

Paul

I’d do it this way:

$LDAPGroupFilter = "(&(objectcategory=group)(objectclass=group)(mailNickname=*)(!mail=*@internal.com)(!cn=zzz*)(!cn=l-*)(!cn=g-*))"

$UserParameters = @{
Filter = $LDAPGroupFilter
Properties = ‘GivenName’,
‘surname’,
‘cn’,
‘mail’,
‘proxyAddresses’
ErrorAction = ‘Stop’
ErrorVariable = ‘ADIssueGroup’
}

Get-ADGroup @Params |
Select-Object -Property $Params.properties

I use splatting when the commands would run too long, or when I need to dynamically build parameter lists. In this specific example, I probably wouldn’t bother, as this code looks fine to me:

$LDAPGroupFilter = "(&(objectcategory=group)(objectclass=group)(mailNickname=*)(!mail=*@internal.com)(!cn=zzz*)(!cn=l-*)(!cn=g-*))"
$properties = 'GivenName', 'surname','cn', 'mail', 'proxyAddresses'

Get-ADGroup -LdapFilter $LDAPGroupFilter -Property $properties -ErrorAction Stop -ErrorVariable ADIssueGroup |
Select-Object -Property $properties

The variable name where the parameters are defined has to match the name that’s used for splatting. You’re using two different ones: $UserParameters versus @Params (Should be $UserParameters and @UserParameters or $Params and @Params). You’re also using the Get-ADGroup -Filter parameter with LDAP Filters. LDAP filters use the Get-ADGroup -LDAPFilter parameter instead (it’s a different parameter set of Get-ADGroup).

Mike,

You are aboslutely right and this is down to my bad copying and pasting from the original script and then attempting to obsufcating internal data. I appreciate the opinions and explanations.

Thanks

Paul

I thought I would re-visit this to give an explanation of what I recommend and what’s going on with the original example that you referenced (since I wrote it):

If you’re new to splatting, I recommend first creating the PowerShell command without the splatting and get a working command before you add additional complexity:


Get-ADUser -Filter * -Properties SamAccountName, Department, Title, LastLogonTimestamp, pwdLastSet, Enabled, LockedOut -ErrorAction Stop -ErrorVariable Problem |
Select-Object -Property SamAccountName, Department, Title, LastLogonTimestamp, pwdLastSet, Enabled, LockedOut

As you can see the previous command is getting very long for one line. Natural line breaks could occur at both the pipe symbol and the commas without having to resort to using the line continuation character (the back tick). I’ll typically start using splatting when lines are getting too long and where some people would start using the back tick for line continuation (the back tick is a problem waiting for a place to happen). I also use splatting where I would have to enter the same information more than once.


$Params = @{
    Filter = '*'
    Properties = 'SamAccountName',
                 'Department',
                 'Title',
                 'LastLogonTimestamp',
                 'pwdLastSet',
                 'Enabled',
                 'LockedOut'
    ErrorAction = 'Stop'
    ErrorVariable = 'Problem'
}

Get-ADUser @Params

Now for the second part of the command. I could create another hash table for the properties I want to display in the Select-Object portion of the command, but I can simply copy the properties to property and then remove the invalid elements and use the same hash table again. Get-ADUser has a parameter named Properties and Select-Object has a parameter named Property (that’s the reason I had to copy properties to property and then remove properties before reusing the hash table with Select-Object).


$Params = @{
    Filter = '*'
    Properties = 'SamAccountName',
                 'Department',
                 'Title',
                 'LastLogonTimestamp',
                 'pwdLastSet',
                 'Enabled',
                 'LockedOut'
    ErrorAction = 'Stop'
    ErrorVariable = 'Problem'
}

$Users = Get-ADUser @Params
 
$Params.Property = $Params.Properties
$Params.Remove('Properties')
$Params.Remove('Filter')
 
$Users | Select-Object @Params

The negative aspect of the way I did this, is you could have a bottleneck with trying to store the users accounts in a variable when the pipeline could have been used instead.

Last but not least, I recommend reading the about_Splatting help topic in PowerShell. Rohn Edwards actually wrote that help topic. Rohn who along with me is the co-founder of the Mississippi PowerShell User Group. He won the advanced category in the 2012 Scripting Games (the year before I won it).