General

Correct File Encoding

Make sure all files are encoded using UTF-8 (not UTF-8 with BOM), except mof files which should be encoded using ASCII. You can use ConvertTo-UTF8 and ConvertTo-ASCII to convert a file to UTF-8 or ASCII.

Descriptive Names

Use descriptive, clear, and full names for all variables, parameters, and functions. All names must be at least more than 2 characters. No abbreviations should be used.

Bad:

$r = Get-RdsHost

Bad:

$frtytw = 42

Bad:

function Get-Thing
{
    ...
}

Bad:

function Set-ServerName
{
    param
    (
        $mySTU
    )
    ...
}

Good:

$remoteDesktopSessionHost = Get-RemoteDesktopSessionHost

Good:

$fileCharacterLimit = 42

Good:

function Get-ArchiveFileHandle
{
    ...
}

Good:

function Set-ServerName
{
    param
    (
        [Parameter()]
        $myServerToUse
    )
    ...
}

Correct Parameter Usage in Function and Cmdlet Calls

Use named parameters for function and cmdlet calls rather than positional parameters. Named parameters help other developers who are unfamiliar with your code to better understand it.

When calling a function with many long parameters, use parameter splatting. If splatting is used, then all the parameters should be in the splat. More help on splatting can be found in the article About Splatting.

Make sure hashtable parameters are still properly formatted with multiple lines and the proper indentation.

Bad:

Not using named parameters.

Get-ChildItem C:\Documents *.md

Bad:

The call is very long and will wrap a lot in the review tool when the code is viewed by the reviewer during the review process of the PR.

$mySuperLongHashtableParameter = @{
    MySuperLongKey1 = 'MySuperLongValue1'
    MySuperLongKey2 = 'MySuperLongValue2'
}

$superLongVariableName = Get-MySuperLongVariablePlease -MySuperLongHashtableParameter  $mySuperLongHashtableParameter -MySuperLongStringParameter '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' -Verbose

Bad:

Hashtable is not following Correct Format for Hashtables or Objects.

$superLongVariableName = Get-MySuperLongVariablePlease -MySuperLongHashtableParameter @{ MySuperLongKey1 = 'MySuperLongValue1'; MySuperLongKey2 = 'MySuperLongValue2' } -MySuperLongStringParameter '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' -Verbose

Bad:

Hashtable is not following Correct Format for Hashtables or Objects.

$superLongVariableName = Get-MySuperLongVariablePlease -MySuperLongHashtableParameter @{ MySuperLongKey1 = 'MySuperLongValue1'; MySuperLongKey2 = 'MySuperLongValue2' } `
                                                       -MySuperLongStringParameter '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' `
                                                       -Verbose

Bad:

Hashtable is not following Correct Format for Hashtables or Objects.

$superLongVariableName = Get-MySuperLongVariablePlease `
    -MySuperLongHashtableParameter @{ MySuperLongKey1 = 'MySuperLongValue1'; MySuperLongKey2 = 'MySuperLongValue2' } `
    -MySuperLongStringParameter '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' `
    -Verbose

Bad:

Passing parameter (Verbose) outside of the splat.

$getMySuperLongVariablePleaseParameters = @{
    MySuperLongHashtableParameter = @{
        MySuperLongKey1 = 'MySuperLongValue1'
        MySuperLongKey2 = 'MySuperLongValue2'
    }
    MySuperLongStringParameter = '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'
}

$superLongVariableName = Get-MySuperLongVariablePlease @getMySuperLongVariablePleaseParameters -Verbose

Good:

Get-ChildItem -Path C:\Documents -Filter *.md

Good:

$superLongVariableName = Get-MyVariablePlease -MyStringParameter '123456789012349012345678901234567890' -Verbose

Good:

$superLongVariableName = Get-MyVariablePlease -MyString1 '1234567890' -MyString2 '1234567890' -MyString3 '1234567890' -Verbose

Good:

$mySuperLongHashtableParameter = @{
    MySuperLongKey1 = 'MySuperLongValue1'
    MySuperLongKey2 = 'MySuperLongValue2'
}

$superLongVariableName = Get-MySuperLongVariablePlease -MySuperLongHashtableParameter $mySuperLongHashtableParameter -Verbose

Good:

Splatting all parameters.

$getMySuperLongVariablePleaseParameters = @{
    MySuperLongHashtableParameter = @{
        MySuperLongKey1 = 'MySuperLongValue1'
        MySuperLongKey2 = 'MySuperLongValue2'
    }
    MySuperLongStringParameter = '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'
    Verbose = $true
}

$superLongVariableName = Get-MySuperLongVariablePlease @getMySuperLongVariablePleaseParameters

Good:

$superLongVariableName = Get-MySuperLongVariablePlease `
    -MySuperLongHashtableParameter @{
        MySuperLongKey1 = 'MySuperLongValue1'
        MySuperLongKey2 = 'MySuperLongValue2'
    } `
    -MySuperLongStringParameter '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' `
    -Verbose

Correct Format for Arrays

Arrays should be written in one of the following formats.

If an array is declared on a single line, then there should be a single space between each element in the array. If arrays written on a single line tend to be long, please consider using one of the alternative ways of writing the array.

Bad:

Array elements are not format consistently.

$array = @( 'one', `
'two', `
'three'
)

Bad:

There are no single space beetween the elements in the array.

$array = @('one','two','three')

Bad:

There are multiple array elements on the same row.

$array = @(
    'one', 'two', `
    'my long string example', `
    'three', 'four'
)

Bad:

Hashtable is not following Correct Format for Hashtables or Objects.

$array = @(
    'one',
    @{MyKey = 'MyValue'},
    'three'
)

Bad:

Hashtables are not following Correct Format for Hashtables or Objects.

$myArray = @(
    @{Key1 = Value1;Key2 = Value2},
    @{Key1 = Value1;Key2 = Value2}
)

Good:

$array = @('one', 'two', 'three')

Good:

$array = @(
    'one',
    'two',
    'three'
)

Good:

$array = @(
    'one'
    'two'
    'three'
)

Good:

$hashtable = @{
    Key = "Value"
}

$array = @( 'one', 'two', 'three', $hashtable )

Good:

$hashtable = @{
    Key = "Value"
}

$array = @(
    'one',
    'two',
    'three',
    $hashtable
)

Good:

$myArray = @(
    @{
        Key1 = Value1
        Key2 = Value2
    },
    @{
        Key1 = Value1
        Key2 = Value2
    }
)

Correct Format for Hashtables or Objects

Hashtables and Objects should be written in the following format. Each property should be on its own line indented once. There should be no space between the brackets of an empty hashtable.

Bad:

$hashtable = @{
}

Bad:

$hashtable = @{Key1 = 'Value1';Key2 = 2;Key3 = '3'}

Bad:

$hashtable = @{ Key1 = 'Value1'
Key2 = 2
Key3 = '3' }

Good:

$hashtable = @{}

Good:

$hashtable = @{
    Key1 = 'Value1'
    Key2 = 2
    Key3 = '3'
}

Good:

$hashtable = @{
    Key1 = 'Value1'
    Key2 = 2
    Key3 = @{
        Key3Key1 = 'ExampleText'
        Key3Key2 = 42
    }
}

Correct use of single- and double quotes

Single quotes should always be used to delimit string literals wherever possible. Double quoted string literals may only be used when it contains ($) expressions that need to be evaluated.

Bad:

$string = "String that do not evaluate variable"

Bad:

$string = "String that evaluate variable {0}" -f $SomeObject.SomeProperty

Good:

$string = 'String that do not evaluate variable'

Good:

$string = 'String that evaluate variable {0}' -f $SomeObject.SomeProperty

Good:

$string = "String that evaluate variable $($SomeObject.SomeProperty)"

Good:

$string = 'String that evaluate variable ''{0}''' -f $SomeObject.SomeProperty

Good:

$string = "String that evaluate variable '{0}'" -f $SomeObject.SomeProperty

Correct Format for Comments

There should not be any commented-out code in checked-in files. The first letter of the comment should be capitalized.

Single line comments should be on their own line and start with a single pound-sign followed by a single space. The comment should be indented the same amount as the following line of code.

Comments that are more than one line should use the <# #> format rather than the single pound-sign. The opening and closing brackets should be on their own lines. The comment inside the brackets should be indented once more than the brackets. The brackets should be indented the same amount as the following line of code.

Formatting help-comments for functions has a few more specific rules that can be found here.

Bad:

function Get-MyVariable
{#this is a bad comment
    [CmdletBinding()]
    param ()
#this is a bad comment
    foreach ($example in $examples)
    {
        Write-Verbose -Message $example #this is a bad comment
    }
}

Bad:

function Get-MyVariable
{
    [CmdletBinding()]
    param ()

    # this is a bad comment
    # On multiple lines
    foreach ($example in $examples)
    {
        # No commented-out code!
        # Write-Verbose -Message $example
    }
}

Good:

function Get-MyVariable
{
    # This is a good comment
    [CmdletBinding()]
    param ()

    # This is a good comment
    foreach ($example in $examples)
    {
        # This is a good comment
        Write-Verbose -Message $example
    }
}

Good:

function Get-MyVariable
{
    [CmdletBinding()]
    param ()

    <#
        This is a good comment
        on multiple lines
    #>
    foreach ($example in $examples)
    {
        Write-Verbose -Message $example
    }
}

Correct Format for Keywords

PowerShell reserved Keywords should be in all lower case and should be immediately followed by a space if there is non-whitespace characters following (for example, an open brace).

Some reserved Keywords may also be followed by an open curly brace, for example the catch keyword. These keywords that are followed by a curly brace should also follow the One Newline Before Braces guideline.

The following is the current list of PowerShell reserved keywords in PowerShell 5.1:

begin, break, catch, class, continue, data, define do, dynamicparam, else,
elseif, end, enum, exit, filter, finally, for, foreach, from, function
hidden, if, in, inlinescript, param, process, return, static, switch,
throw, trap, try, until, using, var, while

This list may change in newer versions of PowerShell.

The latest list of PowerShell reserved keywords can also be found on this page.

Bad:

# Missing space after keyword and before open bracket
foreach($item in $list)

Bad:

# Capital letters in keyword
BEGIN

Bad:

# Violates 'One Newline Before Braces' guideline
begin {
    # Do some work
}

Bad:

# Capital letters in 'in' and 'foreach' keyword
ForEach ($item In $list)

Good:

foreach ($item in $list)

Good:

begin
{
    # Do some work
}