PowerShell Best Practices To Follow When Coding¶
It is important to follow best practices when coding in PowerShell to ensure that your codes are efficient, maintainable, and secure.
Specify The Variable Types Explicitly¶
🚫 Don't do this
✅ Do this instead
Use Full Type Names Instead of Type Accelerators¶
🚫 Don't do this
✅ Do this instead
Use Single Quotes Instead of Double Quotes Unless Absolutely Necessary¶
🚫 Don't do this
✅ Do this instead
This is because double quotes allow for string interpolation, which can be a security risk if the string is not sanitized properly and also slightly slower than single quotes.
Use Full Cmdlet Names Instead of Aliases¶
🚫 Don't do this
✅ Do this instead
Use Pascal Casing for Everything¶
🚫 Don't do this
🚫 or this (camelCase)
✅ Do this instead
Use Regions to Organize Your Code¶
✅ Using regions like this allows you to collapse and expand sections of your code for better readability.
#Region Functions
function Get-MyFunction1 {
# Function code here
}
function Get-MyFunction2 {
# Function code here
}
function Get-MyFunction3 {
# Function code here
}
#EndRegion
Use Visual Studio Code PowerShell Extension For Automatic Best Practice Formatting¶
You can access the settings page of PowerShell extension in VS Code and enable options that automatically apply some of the aforementioned best practices when you format your code with (CTRL + Shift + F) shortcut.
Refrain From Defining and Using Global Variables as Much as Possible¶
Global variables are not recommended in general because of security implications. They can be overwritten by the user on console as well.
If you need to define global variables, make sure you set them as constants or read-only so that they cannot be overwritten once they are defined.
Use C# If You Need Custom Global Classes¶
If you need custom types in PowerShell and want them to be globally available to your module, It's recommended to use C# and define custom classes with specific and unique Namespace and Class names so that there won't be any possible conflicts with other classes/types that belong to 3rd party modules.
How Would You Make PowerShell Classes Globally Available?¶
Even though it's not recommended, here is how you can make custom classes globally available in PowerShell. Classes will be available process-wide and therefore also in other runspaces, defining them with the [NoRunspaceAffinity()]
attribute.
[NoRunspaceAffinity()]
Class Items : System.Management.Automation.IValidateSetValuesGenerator {
[System.String[]] GetValidValues() {
$Items = ('Item1', 'Item2', 'Item3')
return [System.String[]]$Items
}
}
[NoRunspaceAffinity()]
Class BasePolicyNames : System.Management.Automation.IValidateSetValuesGenerator {
[System.String[]] GetValidValues() {
[System.String[]]$BasePolicyNames = foreach ($Policy in (&'C:\Windows\System32\CiTool.exe' -lp -json | ConvertFrom-Json).Policies) {
if ($Policy.IsSystemPolicy -ne 'True') {
if ($Policy.PolicyID -eq $Policy.BasePolicyID) {
$Policy.FriendlyName
}
}
}
return $BasePolicyNames
}
}
# Define the types to export with type accelerators.
[System.Reflection.TypeInfo[]]$ExportableTypes = @(
[Items]
[BasePolicyNames]
)
# Get the non-public TypeAccelerators class for defining new accelerators.
[System.Reflection.TypeInfo]$TypeAcceleratorsClass = [psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')
# Add type accelerators for every exportable type.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
# !! $TypeAcceleratorsClass::Add() quietly ignores attempts to redefine existing
# !! accelerators with different target types, so we check explicitly.
$Existing = $ExistingTypeAccelerators[$Type.FullName]
if (($null -ne $Existing) -and ($Existing -ne $Type)) {
throw "Unable to register type accelerator [$($Type.FullName)], because it is already defined with a different type ([$Existing])."
}
$TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
More Resources From Microsoft That You Should Check Out¶
- Cmdlet Development Guidelines
- Required Development Guidelines
- Strongly Encouraged Development Guidelines
- Advisory Development Guidelines