Skip to main content

Learning PowerShell: A Bash Fan's Experience

Being fairly new to LinkedIn, I figured it would be a good idea to post some of my recent work. I've gotten pretty comfortable writing Linux Bash scripts over the last few years, but I've tended to shy away from PowerShell because it always seemed too wordy by comparison. Of course, PowerShell's greatest sin against me was that there was no direct analog for grep.

Well, I decided to learn my way around PowerShell this month to automate some password changes for kiosk-style accounts. Turns out, PowerShell is actually pretty awesome. It took some time to transition my brain away from the string manipulation techniques common in Bash coding to object manipulation in PowerShell, but I came out stronger on the other end.

The script I wrote is part of a larger deployment project, a full writeup of which you can find at my website here. I won't include the full script here, but I'll cover some highlights.

By far, the most useful thing that I learned to use are hashtables, which I used for results tracking. I collected results from various functions using this bit of code:

{
    $Results[$Computer] += @{$Task = & $Task} # Call task and add output to $Results
    Write-Host -ForegroundColor Green "$($Computer): $Task - $($Results.$Computer.$Task)"
}

and I would print out results using this function

function Print-Summary # Output results summary for all tasks run
{
	Write-Host -BackgroundColor White -ForegroundColor Black "`nResults Summary`n"
	foreach ($Computer in $Results.Keys)
	{
		Write-Host -BackgroundColor DarkBlue -ForegroundColor White "$($Computer)"
		foreach ($Record in $Results.$Computer)
		{
			$Record | Format-Table -Autosize
		}
	}
}

I also discovered loop labels, which saved me from having to write some extra code to break out of an internal loop. I gave my primary outer loop the UserLoop label

:UserLoop foreach ($User in $Users)

and added it to the end of a catch block where I needed to skip the rest of the inner TaskLoop

catch # Skip remaining tasks in current loop if exception occurs
{
	Write-Host -ForegroundColor Red "$($Computer): $Task - $($_.exception.message)"
	$Results[$Computer] += @{$Task = $_.exception.message}
	Fail-RemainingTasks -Message "Process failed at $Task"
	Write-Host "$($Computer): Skipping reboot because of unsuccessful task(s)"
	continue UserLoop # Point back to top of user loop
}

I am grateful to have added PowerShell scripting to my toolkit this month, and I am already looking at other ways to script away some other tedious manual tasks.

Thanks for reading!