Event 3: My notes…

Time to summarize 3rd event of Scripting Games 2013. I must admin – I learn few new tricks while reading entries for this event. But I still see some things I really can’t stand. Especially in beginner category, where many people decided that putting everything in one line makes it “special”. It doesn’t. If you still think it does – read this article by Richard Siddaway. If you still think line break is cursed – read it again. Repeat. Puszczam oczko

Positives first – beginners

But before I start complaining, few words about cool things I’ve seen in this event.

First thing is the use of –Filter. It’s not a surprise, but I was glad to see that so many people in this category do realize that filter-left is important. Another think that I liked was correct use of here-strings constructs. Much easier to read and work with than lines and lines of string concatenation, especially when used with “normal” strings.

Another important element was proper use of ConvertTo-Html cmdlet. Most of people did it better than I did, using –PreContent and –PostContent. Also, I was not aware that these parameters accept string arrays (never read help for those), and was happy to see others actually read documentation and used that parameters to fully benefit from that, e.g.:

ConvertTo-Html (...) -PostContent '<hr>', (Get-Date)

But one thing simply blew my mind. I had no idea that ConvertTo-Html accepts hashtables for –Property parameter (in similar way Select-Object and Format-Table do). I’ve never tried it, and couldn’t find documentation for it. Syntax of hashtable is similar to the one that is used for tables from v1 days (read: it does not accept key “Name”):

Get-Process | ConvertTo-Html -Property @{            
    Label = 'Process Name'            
    Expression = { $_.Name }            
}, @{            
    Label = 'Process Id'            
    Expression = { $_.Id }            
}, @{            
    Label = 'Path to executable'            
    Expression = { $_.Path }            
} | Out-File Processes.html            

For me it’s yet another prove that you can learn new things about PowerShell every day, regardless of how long you’ve used it already. Puszczam oczko

Negatives – beginners

I already mentioned my main “style” issue with many entries. But from coding perspective, the worse was using Where-Object to filter out disks, or – no filtering at all. My first code was also missing this piece (until I’ve tested it on workstation that had several disks mapped). This is important piece – make sure your code does what it suppose to do, and make it as efficient as possible. If you have a way to filter on remote side, don’t pull everything and rely on Where-Object. As contrast for using here-string, I’ve seen several entries that used number of lines of $foo += ‘Another line of HTML’. If you really want to build strings like that, use StringBuilder class instead. Why? Well, strings has same issue as arrays… When you add something to string, you are replacing it with bigger string.

Finally something that was hard for me to understand. Seen few entries with param blocks created, but not exposed as parameters at all. If you define few variables at the beginning of the script, there is no reason why you shouldn’t surround them with param () block, separate them with commas and have nice parameters with default values. So little work and benefit is obvious. Compare the two:

# I can run this script (and TAB-complete!) both -ComputerName *and* Path            
param (            
$ComputerName = $env:COMPUTERNAME,            
$Path = '.\'            
# I have to *edit* this script whenever I want to change how it works...            
$ComputerName = $env:COMPUTERNAME            
$Path = '.\'            

Positives – advanced.

In advanced category I appreciated most of the elements I already mentioned above. On top of those I really liked when author separated script logic into few smaller functions that were performing only part of work. I’ve noticed that many scripters understand and use splatting – awesome! What else? Helpful aliases for ComputerName: if it takes value from pipeline ByName, aliases can be bound to. So aliases such as __Server or Name can simplify piping different objects, that do no have ComputerName property on them, without a need to use script block ( –Computername { $_.Name }) or select object.

I’ve also seen few entries that were taking advantage of runspace pools, and other clever techniques. Finally – something new in PowerShell v3, that is not known very well and not used as much as it might have been: nice descriptions for default parameters. Example not related to task:

function Get-HelpfulDefault {            
    Only test help...
param (            
[PSDefaultValue(Help = 'Current date')]            
[DateTime]$Start = (Get-Date),            
    "Start: $Start End: $End"            

If we take a look at help for the “Start” parameter:


Should not harm to add it, especially if the way you calculate your default value is more complex than simple call to Get-Date.

Negatives – advanced.

On top of obvious things, like using Where-Object or lack of filtering, I would like to add two things. First one is related of wasting own time on re-inventing the wheel. PowerShell cmdlet ConvertTo-Html works very well, no reason to replace it with custom implementation that does more or less the same, but in less efficient and smart way… Second thing is related to parameters. I don’t see any benefit in using parameters names that are not common with cmdlets that we’ve known and used for years. If you want to use parameter –Server – define it as alias for parameter ComputerName. There is one exception to this related to the bug with ActiveDirectory module, but other than that – you really shouldn’t make up parameters, unless what you are defining is really unique. Name of the Computer that you want to target those not fall into this category.

Neutral – advanced.

Few last words are related to two other things I wouldn’t call “negative”. First one is related to calling cmdlets with variables. If you simply want to pass variable to parameter – there is no need for sub-expression. In this context sub-expression make sense only if you access properties of object stored in variable, and even that is needed only in very complicated calls (usually – quoted)

$ProcessName = 'explorer'            
$Process = Get-Process -Id $PID            
# NOT needed:            
Get-Process -Name $ProcessName            
Get-Process -Name $Process.Name            
$System32 = Get-Item $env:windir\System32            
# Needed:            
Get-Item "$($System32.FullName)\Drivers"            

Another thing is the use of if/ else. Very often the code is repeated twice, with some elements added in either case. Instead, you can simply define “common” part outside, and get rid of one of the clauses. I will use creating splatting hashtable as an example:

$WmiParams = @{            
    Class = 'Win32_LogicalDisk'            
    ErrorAction = 'Stop'            
if ($Credential) {            
    $WmiParams.Credential = $Credential            

I don’t expect any performance benefits here, but in my opinion it’s more clear what is my intent: I want to define $WmiParams hashtable regardless of value of $Credential. But only if it’s present – I want to include it in my hashtable. Same applies to any situation where some actions are taken in both “scenarios”.


One thought on “Event 3: My notes…

  1. Pingback: The 2013 Scripting Games, Beginner Event #3 | Mello's IT Musings

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s