JackBennett

What Working In Powershell Looks Like

There's tons of content about how to write code, function modules etc. I wanted to write about what your work might look like when using code as part of your toolbox. Given how powershell has all the power to write an application, but the purpose to script things, what do you do with it? What does it look like to work with it? How does it change your thinking? What new approaches to problems are there?

# The Task

You're asked if it's possible to copy a set of lesson materials to all the students folders in a class. I'm sure initial thoughts are;

  1. Use the shared drive.
  2. Use the shared drive.

But hey, we know powershell, so this isn't really a big deal;

$listOfUsernames | % { cp -Recurse "\\shared\lesson\lesson_template\*" "\\server\users\$psitem\lesson6\" }

Populating $list_of_usernames is an exercise for the reader. Once we've a need for selections like that it becomes worth the effort to go beyond typing a list of names manually.

If you are new to PS the above is simply shorthand to loop over the contents from $listOfUsernames. There's aliases in the language to save typing when it's yourself putting the effort in on the command line. The exact same code I should write in a script would be;

$list_of_usernames |
  Foreach-Object {
    # For each username in the class list copy the files into a folder.
    Copy-Item -Recurse -Path "\\shared\lesson\lesson_template\*" -Destination "\\server\users\$psitem\lesson6\"
  }

Same code, much clearer. You could use get-alias to figure this out yourself. get-alias gal # gal -> Get-Alias, gal %, gal cp etc.

Great, at this point job done. There's always more that can be done though if you think about it, is there any opportunity here to save some work in the future? Perhaps even add value in a new way.

# Have someone else do the work

It's probably fair to say such a request may come up more often now that you've shown how easy it was.

First off let's deal with this user list business, often class lists in school aren't the easiest to get programatically;

  1. Inconsistent naming conventions
  2. Outdated lists
  3. Teacher not knowing exactly the right class name that matches whatever naming scheme you have it saved in

All we need is the script in a shared location, which we run applications from already, great!

# v1 \\server\applications\powershell\start-lesson6.ps1

copy-item -Recurse "\\shared\lesson\folder\*" "H:\Lesson6\" -force

Any user can call that themselves and get setup for the class. Hang on though, now people who don't know what the script does are going to be calling it, so it's on us to be more careful. Currently there's a few issues with this code;

  1. copy-item -force to create the target folder is going to overwrite those files every time its run!
  2. This file is very specific about lesson6 and where it goes
  3. Absolutely no useful information is given to the user.

# Security

A note on security, Code Signing allows our scripts to be locked up and ran by anyone i.e. the students themselves. Should the contents of the script change it will invalidate the signature and powershell can refuse to run it. There are ways around signing so you should think of it as marking a script as authentic from an author rather than a security wall.

# Coding For Reuse

Generalise this script to use it in future for something else without modification. As we're leaving code around to read later (possibly years later) lets help others (and future you) by using the long-form cmdlet names for clarity.

# v2 \\server\applications\powershell\start-lesson.ps1
Param(
  $Path,
  $Destination
)
new-item -type Directory $Destination -errorAction Stop
copy-item -Recurse $Path $Destination

# Reaping the benefits

Sure enough, the next morning you're told to use different names for the folder and do 3 extra topics for the class. Oh and if possible, in the next hour please. Make a few more shortcuts changing the parameter info and done. Dead easy and you don't have to know powershell to do it, this is what being a force multiplier on a team looks like. Once this has been used a few times it justifies adding more to the script;

  • Why not handle if the files have already been copied?
  • Perhaps write some information to the user?
  • Split the copy into steps for guiding users?
  • Pick up copying files from where the user left off.

The script currently in use is on github here. If you are reading this far, might I point out the history tab to review how this has evolved.