One of the things I discovered with doing a lot of PowerShell is that I ended up with a TON of snippets, notes, and random .ps1 files that could be a script, could be a function, or they could just be a loosely related collection of one-liners. I have saved practically everything I have ever found to be useful and used to do a ton of copy/paste when writing new scripts.
Today I’m here to say that if you do this, you need to stop that. Right now. Start building tools.
Tools vs scripts
Let me first start by giving you my definition of a PowerShell script and a PowerShell tool.
A PowerShell script is PowerShell code that does a collection of tasks, typically all related somehow. It’s not exciting, it can be flashy, but it does the job.
A good example of a script is when you have a scheduled task that does some monthly AD clean-up. It finds stale user and computer accounts and takes appropriate action, hopefully writing good logs if you had enough time to implement logging.
A PowerShell tool is PowerShell code that is does one specific task and it does it well.
A good example of a tool is if in your AD clean-up script, you wrote a custom function to filter the stale objects from Search-ADAccount for accounts that had also not yet logged on: Get-ADStaleAccounts is what you’d decided to call it.
Based on my definitions, you can write a script using your tools, but a tool cannot use a script you wrote.
Finding code to turn into tools
There are two really easy ways to find code that is ripe to be turned into a reusable tool:
- You copy and paste a section of code from one script to another
- You often type the same or similar one-liner when doing normal administrative tasks
For instance, one of the first functions I ever wrote was a simple:
Get-ADLastLogon. I got sick and tired of writing:
get-aduser theposhwolf -properties lastlogondate | ft name,lastlogondate
So I wrote a function that accepted a user as the only argument and returned the user’s last logon date. Took me maybe an hour back then to get all the syntax right, but it saved me 5-seconds every time I chose to run it. (For those of you that math, that would be 720 times to receive an ROI)
Another piece of code that I found myself copying and pasting a lot was simple code that I had for converting large file and folder sizes to readable sizes. For instance, I wrote a
Get-ItemSize function that returned the size of a folder in bytes. The only problem with that is how big is a 568435752960 shared folder? Using my
Format-Bytes function, I can easily tell you that it is
529.40 GB. Why would I ever need to know that though? I’m not the only person that cares about shared file sizes, what happens when you send that information as a .csv to your CTO to convince that we need more storage? While it would be amusing to send the size in raw bytes, we also like to be nice to our non-technical managers since they hopefully will sign the checks for new shiny things, so I like to do them a favor and math it for them.
Scripts still have their place, of course
One of the things you’ll find with building tools is that writing scripts becomes much easier. You’ll put yourself into the position where your scripts are easier to write and easier to read because you’ve taken all of your menial tasks out into functions. Suddenly you spend more of your time focusing on the important things like learning about the new Windows Admin Center instead of trying to find the snippet of code you wrote for remotely querying the registry for installed software.
It does introduce some complexity though: How do you build tools and easily use them? Should you just import each function each time you need it? Maybe build a module? Or multiple modules?
Well, I’ve gone through and drafted up a blog series I’d like to do on tool building as that is what I’m passionate about. If you’ve ever seen my demos on TechSnips you know that I advocate for building reusable functions.
With my backlog filled, I’m hoping to be a bit more consistent with posts. Thanks for taking the time to read through this!