Monday, March 21, 2016

Powershell: Using optional paramaters

Have you ever created a cmdlet that was a wrapper for another command but you added optional parameters. This is a very common pattern. But how do you pass or not pass that optional parameter to the underlying command? How often do you create an if or switch to check for it and have the function call in your code twice? Once with the param and once with out it.

This is such a common pattern especially when dealing with credentials. I saw this example in someone else's code:

if($Credential)
{
    foreach($Computer in $ComputerName)
    {
        $Disks += Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter "DeviceID='C:'" -Credential $Credential -ErrorAction SilentlyContinue
    }
}
else
{
    foreach($Computer in $ComputerName)
    {
        $Disks += Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter "DeviceID='C:'"
    }
}

The credential was optional to his use of the cmdlet. I just don't like to see code repeated like that. Sure, he could have placed the if logic inside the foreach loop. But he still has logic in two places. I see the error action is set to SilentlyContinue for one of them. I can't tell if that is intentional or it should have been on both.

This is that same code but using a hashtable and splatting to deal with the optional parameter.

$LogicalDiskArgs = @{
    Class  = 'Win32_LogicalDisk'
    Filter = "DeviceID='C:'"       
}

if($Credential)
{
    $LogicalDiskArgs.Credential  = $Credential
    $LogicalDiskArgs.ErrorAction = 'SilentlyContinue'
}

foreach($Computer in $ComputerName)
{
    $Disks += Get-WmiObject @LogicalDiskArgs -ComputerName $Computer
}

The use of splatting makes this really easy to do. I like how this really shows the intent of using that error action with the optional parameter. 

 

Wednesday, March 16, 2016

Showing the intent of your code in Powershell

I hang out on /r/Powershell quite often and I find myself talking about writing code that shows your intent quite often. When I initially started working with Powershell I was kind of put off by the verbosity of it. Over time I came to accept it and things like tab complete make it easy to work with.

I turned that corner a long time ago and really like the verbosity of it now. When you combine that with clean code best practices that create self documenting code, Powershell becomes so easy to read and work with. I like it when my code makes it very easy to see what the intent of it is. I share a lot of code so this is something I find to be important in my work.

My simple example is trying to split a string and skipping the first item in the list. This is the code sample that was getting passed around:

$obj = (Get-ADGroup 'GroupName').DistinguishedName.split(',')
$obj[1..$($obj.count - 1)]


It worked and accomplished the goal. But compare it to this and think about what one shows the intent of the code better.

(Get-ADGroup 'GroupName').DistinguishedName -split ',' |  Select-Object -Skip 1


In my code, I would take it one more step.

$ADGroup = Get-ADGroup 'GroupName'
$ADGroup.DistinguishedName -split ',' |  Select-Object -Skip 1


 All three of them are valid Powershell and this just a style preference, but having a solid and consistent can make your code a lot easier to read.