If you’ve been using PowerShell for any amount of time you’ve probably written a lot of code. Here are some guidelines I’ve come up with for what I consider “Professional” code. I should note that I’m assuming some basic things like correct verb-noun naming, commented code, reasonable variable names, etc. Also, the code should work! Once you’ve got that going, try to make sure you’ve got these as well.

Output objects This should go without saying, but it’s vitally important. Write objects to the output stream. Each object should be a self-contained a “record” of output. If you’re creating custom objects, consider including some of the parameter values that led to the object being output. If possible, It should contain enough information to let you know why it was output. For instance, if your parameters filter the output based on properties, including those properties will be very helpful in validating that the output is correct.

Advanced functions (or script) Changing a function into an advanced function can be as simple as adding [CmdletBinding()] before the Param() statement. It does take a bit more if you need to support -WhatIf and -Confirm, but even then it’s not much effort. In return you get: Common Parameter Support (Verbose, ErrorAction, etc.)

Parameter Name and Position Checking

Access to $PSCmdlet methods and properties

Ability to use pipeline input (in a nice way) If you need help getting started with writing advanced functions (or scripts), see about_Functions_CmdletBindingAttribute

Comment-based help This one takes a bit more work, but is a key to getting other people to use your function or script effectively. It’s simple to write up a code snippet for ISE (or your editor of choice) to include the help elements you like. Most people will start by skipping to the examples, so always include multiple examples! Examples which show different use-cases (parameter sets, if you use them, for instance) are especially helpful so that users understand the full range of how your code can be used. Refer to get-help about_Comment_Based_Help to get you started.

Pipeline input Pipeline input isn’t always necessary, but it really makes using a function easier. You’ve got to have an advanced function to do this, but you did that already, right? I’d much rather have this: Get-Thing | Stop-Thing Than this: Get-Thing | foreach-object {Stop-Thing $_} If you’ve used cmdlets that didn’t allow pipeline input you’ve undoubtedly written some code like this.

Error Handling This is pretty basic. You need to use try/catch/finally in your code to deal with exceptions that you can predict. You should use Write-Error and Throw to emit errors and exceptions that arise. If you use Write-Error, supply a -TargetObject if possible, it makes the error record much more useful. While we’re talking about errors, Write-Warning, Write-Verbose, and Write-Debug should be used to help provide useful output

Parameter Attributes for validation Here’s a good rule of thumb: Code that you don’t write is code that you don’t have to debug! If you use parameter attributes to validate argument values, you don’t have to write code to do it. Ensuring that arguments are valid will make users happier (because they don’t have unexpected results when they pass in bad values) and makes your code simpler because you don’t have to write a bunch of if/then statements to check values. Finally, and this benefit is not as obvious, error messages for parameter attribute-based validation will be localized, so users around the world can benefit even more from your code as they see validation messages in their own language..