Creating functions is among the most frequent tasks you will run into when working in PowerShell long enough. PS functions serve a fundamental role, as a component to help us organize and encapsulate our code, and reuse it. Without functions scripts would become overly complex, cluttered with numerous if/else statements or loops and repetitive code segments.
By using functions, we bundle our PowerShell logic into manageable units that can be invoked as needed. They allow us to pass parameters to modify their behavior and promote code reuse. To me, code reuse is EVERYTHING in every coding lang, adhering to the DRY (Don’t Repeat Yourself) principle.
So here are a couple of tips I want to share for writing functions in PowerShell.
Use PS Naming Convensions
You should name your functions by what action they are doing + the thing involved, aka the verb-noun syntax that PowerShell commands have always used. Go ahead and issue the get-verb command in a PS session, to see the list of approved verbs (actions) that I am talking about. I use this command all the time when I start banging out a quick function.
Consistency is king when writing supportable scripts and functions. So use what PowerShell gives us to maintain consistency and readability. When I see a function named Function IPAddress-DisplayI cringe. To display or report something, I would tell that person to immediate rewrite it using the Get- verb.
Equally important, are if the verb’s action is reading/writing something. Use Get- for reading something in to Display, or later act on. And use Set- when changing data or writingmaking any kind of change. Especially if your function is making some kind of system change.
If you remember nothing else from this blogpost, just remember using PowerShell’s verb-noun naming standard for your functions (and script names, too) will save yourself and your colleagues problems in the future.
Keep your functions Singular in purpose, and Self-Contained
What I mean here is:
- A function in PowerShell should do only one thing (and one thing only) and do it well.
- A function in PS should be modular, or self-contained.
A good self-contained function will have: well-defined input parameters, produces output, and doesn’t rely on external variables to work.
Below is a an example I threw together, to illustrate:
|
|
This PS function is doing one single thing, formatting the date in Output, and the logic and error-handling is done completely within the function itself.
A quick & dirty function, often might not do this is, instead:
|
|
…and that is technically okay, but isn’t necessarily testable and relies on external state to populate a variable. Again, nothing wrong with that but it may not scale for reuse or future needs, being written that way. Also, it’s harder to know what a basic function like this is needed for or reads clearly for anyone else maintaining your code. 😉
Don’t sleep on -WhatIf and -Confirm
Did you know that you can use -Confirm and -WhatIf switches, for dry runs and testing of your functions? Just as you might in a one-liner in a PowerShell session, you can use -WhatIf to see what your function might do, without actually doing it.
Note: using -Confirm and -WhatIf switches only works when writing advanced functions that use -WhatIfSupportsShouldProcess argument. So let’s talk about advanced functions next.
Advanced functions
PowerShell offers a great array of features that you can leverage in your functions, almost effortlessly if you write them as advanced functions.
One advanced function I like to use is if I am doing something destructive to data within an interactive script. As I mentioned above, I can use the SupportsShouldProcess and ConfirmImpact params, so that I can then use -WhatIf or -Confirm switches when calling a function:
|
|
In addition to parameters and using arguments like SupportsShouldProcess to enable -WhatIf capabilities in functions, you can also another one-liner tool in functions: Piplines are another tool and technique you can use in advanced PS functions.
Pipelines in PowerShell advanced functions enable seamless chaining of commands in your scripts, much like they do in interactive PS Sessions. This allows a cmdlet’s output to feed directly into a function, without the need for intermediate variables or complex data handling. This approach simplifies scripts by promoting modularity, reducing code clutter, and making complex tasks more readable and maintainable. Here’s an example:
|
|
In the example above, each input string (Server1 and Server2) is passed directly to Get-Example function through the pipeline. The Process block runs once for each item, simplifying how you handle individual objects. This approach enables your advanced functions to integrate smoothly into larger scripts, toolchains, and DevOps workflows.
Here’s a good link you can refer to on Advanced parameters in PowerShell, but there are a ton of write-ups out to help.
I hope this helped you consider ways to simplify your code, even if PS functions are still an advanced topic for you. Essentially observing the DRY principle will lead you to get good at writing functions, and having clean readable code. Happy coding!