This post is a reprint from an article published to my premium PowerShell newsletter Behind the PowerShell Pipeline available on Substack. Subscribers receive 6-8 articles like this a month delivered to their inbox or available on the Substack app. I hope you'll consider subscribing. Trial subscriptions are available.
Over the course of the last several weeks, I've been sharing and demonstrating techniques for writing effective PowerShell functions. I know I've mentioned a few recommended best practices. But since they are important, I want to review and re-emphasize them. These practices will make your code easier to write, easier to debug or troubleshoot, and more secure. I'd like to think some of them are simple, common sense, but sometimes we need someone to remind us. These items are not in any particular order.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Follow Naming Conventions
Give your functions a meaningful name using the Verb-Noun naming convention. You can give a .ps1 script file any name you want that works for you, but functions should follow the Verb-Noun naming convention. If I can't find the verb portion of your function by running Get-Verb, you've done something wrong. I understand it can sometimes be tricky to find the right verb. But find something as close as possible. You can always create an alias for your function using any verb you wish.
The noun should be singular, although I've been known to bend that rule from time to time. Make the noun meaningful and specific. If there is the possibility of a naming collision, consider adding a prefix to the noun. The prefix could be your initials or maybe an organization abbreviation. The prefix should eliminate naming collisions and make identifying your commands easier.
If you have a naming collision, you can run a command using its fully qualified name:
smbshare\get-smbshare
Specify the command's module name with the command name.
The other critical naming convention is to avoid aliases in your scripts. Feel free to use aliases as much as you want when running PowerShell interactively at a console prompt. But in scripts, use full cmdlet names and parameter names. I would suggest even using parameter names for positional parameters. If you use an editor like VS Code that has Intellisense, it isn't that much of a burden. You only have to write your code once, so write it the right way the first time.
That said, feel free to write your function in VSCode using all the aliases you want. When you are finished, use VSCode to expand your aliases. You can use the command from the command palette or the keyboard shortcut.
Note that this will not add missing parameter names.
Because of the way PowerShell commands are designed, it is practically self-documenting if you use full command and parameter names.
No Passwords
I'd like to think this is a given, but if you need a reminder, do not hard code any passwords or credentials into your scripts and functions.
$pw = "Open$esame!"
...
foo.exe /u administrator /p $pw
And also, avoid this:
Param(
[string]$Name,
[string]$Password
)
If your command needs a password, have the user enter a PSCredential.
Param(
[pscredential]$Credential
)
This doesn't mean the credential object needs to be created ahead of time. The user can specify the username, and PowerShell will prompt for the password.
Another option is to integrate Microsoft's SecretStore and SecretManagement modules.
Be Agnostic
Your PowerShell code should be agnostic. By that, I mean it should not have hard-coded values for things like a domain name. This is bad form.
$domain = "ContosoCorp.pri"
At the very least, use PowerShell to populate the value.
$domain = (Get-ADDomain).DNSRoot
You could also make this a parameter and let the user specify a value. Or, and this is an advanced technique, write your function to use configuration data from a .psd1 file.
If you can't show me your code without having to sanitize it first, I would say you are doing something wrong. It may feel like you are saving time, but I would argue it is actually making your code less secure.
Comments Count
We always talk about the need for internal documentation. Reading PowerShell code should be like reading a story. You should be able to follow the action. If you use full cmdlet and parameter names, that handles the majority of the work. If you include meaningful Write-Verbose messages, that too will fill in the gaps. You only need to add comment sections when running a block of .NET code that might be difficult to understand or for sections of your script that need an explanation about why you are using the code you are. As your code matures and you update it, inserting a comment with a critical change can be helpful.
Code comments are as much for you as the next person. You may be the one looking at code six months later, struggling to figure out what you were trying to achieve.
Make It Pretty
I remember back in my VBScript days. A forum member was having problems with his code. I offered to help, and he posted his code. It was hundreds of lines of single-spaced, left-justified code. It was impossible to read, and VBScript was hard enough. Indentation and white space matters. I just mentioned that your code should tell a story. How your code is displayed in a file can help tell that story. There is no performance penalty for blank lines or white space. If your code is easier to read, it is easier to debug and troubleshoot.
The easiest way to do this is to write your function in VS Code. Right-click on the editor pane, select "Format Document" or use the keyboard shortcut.
The first time I saw this in action, it felt like magic and was the thing that pushed me into the arms of VS Code. You can also configure VSCode to format the file every time you save it.
Summary
I hope that many of you are already following these recommendations. If not, I’d like to know why. You can leave a comment on this article. Perhaps I can clarify or provide additional context. Finding the code to use in your PowerShell scripting project is only part of the job. How you use the code is equally important.