What To Do / Not to Do in PowerShell: Part 3
Take a look at the left-hand side of your keyboard. Odds are, you'll find a key labeled "Tab," or perhaps a key with a "->" symbol on it. Also notice a key labeled "Enter" or "Return," and that big, blank key at the ver bottom. Please make these keys your friend. Why? Take a look at this code:
May 26, 2011
Take a look at the left-hand side of your keyboard. Odds are, you'll find a key labeled "Tab," or perhaps a key with a "->" symbol on it. Also notice a key labeled "Enter" or "Return," and that big, blank key at the ver bottom.
Please make these keys your friend.
Why? Take a look at this code:
function Get-Info {[CmdletBinding()]param([Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)][Alias('host')][string[]]$computername,[string]$logfile='c:failed.txt')BEGIN {Del $logfile -ErrorAction 'SilentlyContinue'}PROCESS {foreach ($computer in $computername) {try { $continue=$true write-verbose "Attempting connection to $computer" $os = Get-WmiObject -class Win32_OperatingSystem -ComputerName $computer -ErrorAction 'Stop'} catch { $computer | Out-File $logfile -append $continue = $False }if ($continue) { $bios = Get-WmiObject -class Win32_BIOS -ComputerName $computer $obj = New-Object -TypeName PSObject $obj | Add-Member -MemberType NoteProperty -Name ComputerName -value ($computer) -passthru |Add-Member -MemberType NoteProperty -Name OSVersion -value ($os.caption) -passthru |Add-Member -MemberType NoteProperty -Name OSBuild -value ($os.buildnumber) -passthru |Add-Member -MemberType NoteProperty -Name SPVersion -value ($os.servicepackmajorversion) -passthru |Add-Member -MemberType NoteProperty -Name BIOSSerial -value ($bios.serialnumber) write-output $obj } } }}
Pretty awful, isn't it? It's hard to read. It's even harder to debug, because it's so poorly-formatted. Whenever I'm teaching class, I tell my students: "If you need help, just ask. But, if your code looks anything like this," and I show them the example above, "don't bother!" I just can't read it.
Now, isn't this version much easier to read and interpret?
function Get-Info { [CmdletBinding()] param( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias('host')] [string[]]$computername, [string]$logfile = 'c:failed.txt' ) BEGIN { Del $logfile -ErrorAction 'SilentlyContinue' } PROCESS { foreach ($computer in $computername) { try { $continue = $true write-verbose "Attempting connection to $computer" $os = Get-WmiObject -class Win32_OperatingSystem -ComputerName $computer -ErrorAction 'Stop' } catch { $computer | Out-File $logfile -append $continue = $False } if ($continue) { $bios = Get-WmiObject -class Win32_BIOS -ComputerName $computer $obj = New-Object -TypeName PSObject $obj | Add-Member -MemberType NoteProperty -Name ComputerName -value ($computer) -passthru | Add-Member -MemberType NoteProperty -Name OSVersion -value ($os.caption) -passthru | Add-Member -MemberType NoteProperty -Name OSBuild -value ($os.buildnumber) -passthru | Add-Member -MemberType NoteProperty -Name SPVersion -value ($os.servicepackmajorversion) -passthru | Add-Member -MemberType NoteProperty -Name BIOSSerial -value ($bios.serialnumber) write-output $obj } } }}
The difference? Tabs. Spaces. Carriage returns. Code within a { construct } of some kind is indented exactly four characters (one tab). That series of Add-Member statements are formatted to line up, visually reminding me that they're all part of the same logical command - see the pipe character at the end of each? PowerShell will recognize that the command continues on the next line when a line ends in a pipe.
It's just a bit of whitespace, but it makes all the difference in the world. So please, format your code!
About the Author
You May Also Like