PowerShell scripting best practices


For the past few years, I’ve picked up a several best practices for PowerShell scripting. Some of them are “borrowed” from Ed Wilson (aka the Microsoft Scripting Guy), Don Jones, and other PowerShell MVPs and PFEs @ Microsoft.

  1. Start your scripts with a standard set of comments (name, date, author, purpose and keywords) to easily find them later.
  2. Add comments as much as possible, but not too much.
  3. Use the #Requires tag for the minimum version of Windows PowerShell required, required Modules, PSSnapin or Administrative rights.
  4. Use the Set-StrictMode -Version Latest command to ensure that you cannot reference things such as  uninitialized variables and non-existent properties of an object.
  5. Use simple but meaningful variable names. (e.g. $ServiceName or $Counter, and not $s and $c).
  6. Place user-defined variables at the top of script. It makes it easier for you or anyone making changes to those script variables.
  7. Use code signing (and the RemoteSigned or AllSigned execution policy).
  8. Don’t use aliases in scripts. Use the full cmdlet name with its named parameters.
  9. Avoid using backticks, they are easy to miss since they might look like dirt on the screen. Instead, use the pipeline (|) character where appropriate, or even splatting the parameters to the cmdlet.
  10. Filter left, format right.
  11. Add the .exe extension to external commands and applications (e.g. there is a big difference between sc and sc.exe).
  12. Don’t turn off pipeline errors ($ErrorActionPreference = “SilentlyContinue”). Implement structured error handling by using Try+Catch+Finally (or Trap) to handle errors.
  13. Do not “pollute” the Windows PowerShell environment by changing preference variables globally (e.g. $ConfirmPreference, $WhatIfPreference, etc.).
  14. Use cmdletBinding and add support for the -WhatIf, -Verbose and -Debug parameters.
  15. Use Advanced Functions.
  16. Use the Verb-Noun naming convention for your functions and filters. When picking out verbs, always use standard verbs. Use Get-Verb to see what verbs are available.
  17. Use standard parameter naming (e.g. ComputerName and not Machine or Server), and set them a default value if relevant (e.g. $ComputerName = $ENV:ComputerName).
  18. A function should do one thing, and do it well.
  19. A function should always return an object or array of objects, not formatted text.
  20. Avoid using the Return keyword. Functions automatically return output to the calling process through the pipeline.
  21. Avoid using Write-Host. It writes to the host, not the pipeline. Prefer using Write-Output over using Write-Host. Write-Host writes to the host, not the pipeline.
  22. Use comment-based help. The minimum items to add are the Synopsis, Description, and Example nodes.
  23. Use Test-Connection (with the -Quiet switch) to ensure a computer is online prior to connecting to it.
  24. Make sure your script is lined up, indented properly, and easy to read. If you can read and understand your script, you will simplify your debugging process.
  25. Keep your script independent from the place you run it (Use $myInvocation.MyCommand.Path or $PSScriptRoot for PowerShell 3.0 and above).
  26. Make sure you test your functions and scripts in a clean environment with no dependencies on profiles, admin rights, and versions to ensure compatibility.
  27. Test scripts in test environment before they are released to production.
  28. Re-use scripts (Package modules, create a script repository).
  29. Implement some processes around script lifecycle (change process)
    • Who can request the creation of scripts?
    • Who is responsible for writing the scripts?
    • Who is responsible for maintaining the scripts?
    • Who is responsible for reviewing (quality control) the scripts?
  30. Follow a simple but organized script flow:
    • #Requires comments
    • Define your params
    • Create your functions
    • Setup any variables
    • Run your code
    • Comment based help

 

If you have any other best practice you’d like to share, use the comments box below. I’ll add it to the list and mention your name too (if you want).

\Martin.

Comments (6)

  1. Nice compilation, thank you!

  2. AnatolSultan says:

    Very interesting article. This will help me for my PowerShell Script (
    http://techsultan.com/category/powershell-2/ )

    Regards

  3. bill says:

    Please don’t tell people what **not** to do. “21.Avoid using Write-Host. It writes to the host, not the pipeline.” You have simply crossed one item off the infite list of possible options and left people little better informed than what they are doing is ‘bad’. Better to indicate the better way. Is this what you intended to say? “21.Prefer using Write-Output over using Write-Host. Write-Host writes to the host, not the pipeline.” Or did you have another preferred option to using Write-Host?

    1. Thanks Bill for the comment. I’ve updated the post as you suggested.

      1. Eduard Babayan says:

        Same goes for Return (20). There is no citation or explanation given. What if I use it? Why not?

  4. Ron Davis says:

    Excellent thanks!

Skip to main content