Functions in PowerShell – All-in-one

All you need to know about functions in PowerShell in one page! All-in-one I didn’t find any resource where I have all information. Of course, there is the official page About Functions Advanced Parameters for advanced features. I lose too much time surfing on different websites, forum etc. I decided to create my own reference and share with everyone interested.

As a pragmatic person, I chose to make it simple, not a lot of text or complicated example including things we don’t need. You should be able to copy-paste the example et use it directly. As this page is intended to include every subject that a function could have, the advantage of the one-page is that we can easily find the information with CTRL + F.

Define parameters that can be received

Accept param from pipeline

[cmdletbinding()]
param(
	[Parameter(Mandatory=$true, ValueFromPipeline)][string]$VarFromPipeline
)

Is the parameter mandatory?

param(
	[Parameter(Mandatory=$true)]$MyString,
    [Parameter(Mandatory=$false)]$MyInt,
    [Parameter(Mandatory=$true)]$MySecondString = "Second string"
)

If the parameter is not mandatory, you can then set a default value.

Define types

param(
	[Parameter(Mandatory=$true)][string]$MyString,
    [Parameter(Mandatory=$true)][int]$MyInt,
    [Parameter(Mandatory=$true)][double]$MyDouble,
    [Parameter(Mandatory=$true)][float]$MyFloat,
    [Parameter(Mandatory=$true)][DateTime]$MyDateTime,
    [Parameter(Mandatory=$true)][switch]$MySwitch 
    # ...
    
)

By defining the type, you ensure your function receive the proper type of variable

Switch parameters are parameters with no parameter value. They’re effective only when they’re used and have only one effect.

Group of parameters

    param(
        [Parameter(Mandatory=$true)]
        [string]$Symbol, 
          
        [Parameter(Mandatory=$true, ParameterSetName = 'Time')]
        [string]$StartTime,

        [Parameter(Mandatory=$true, ParameterSetName = 'Time')]
        [string]$EndTime,

        [Parameter(Mandatory=$true, ParameterSetName = 'Limit')]
        [ValidateRange(1, 1000)]
        [int]$Limit
    )

The ParameterSetName argument specifies the parameter set to which a parameter belongs. If no parameter set is specified, the parameter belongs to all the parameter sets defined by the function. Therefore, to be unique, each parameter set must have at least one parameter that isn’t a member of any other parameter set.

More information

Dynamic parameters

function Test-Order{
   
    [cmdletbinding()]

    param(
        [Parameter(Mandatory=$true)] 
        [ValidateSet("Market", "Limit", "TakeLimit")]
        [string]$OrderType
    )

    DynamicParam{
        # param1
        $attributes = New-Object -Type System.Management.Automation.ParameterAttribute
        $attributes.Mandatory = $true
        $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
        $attributeCollection.Add($attributes)
        $dynParam = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Price", [double], $attributeCollection)

        #param2
        $attributes2 = New-Object -Type System.Management.Automation.ParameterAttribute
        $attributes2.Mandatory = $true
        $attributeCollection2 = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
        $attributeCollection2.Add($attributes2)
        $dynParam2 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("StopPrice", [double], $attributeCollection2)

        # add to dictionnary
        $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
        $paramDictionary.Add("Price", $dynParam)
        $paramDictionary.Add("StopPrice", $dynParam2)
        
        return $paramDictionary
    }

    BEGIN{
        $Price     = $paramDictionary.values[0].value[0]
        $StopPrice = $paramDictionary.values[0].value[1]

        write-host $paramDictionary.values[0].name[0]
        write-host $paramDictionary.values[0].value[1]
      
    }

    PROCESS{
        Write-Host "Price:     $Price"
        write-host "StopPrice: $StopPrice"
        write-host "orderType: $OrderType"
    }
}

I noticed that it fails if your parameter has space. You can only add DynamicParam once in your function. You must add the PROCESS script block.

More information or this website

Valid parameters received

Valid a set of value

param(
	[Parameter(Mandatory=$true)] 
		[ValidateSet("1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","1d","3d","1w","1M")]
		[string]$Interval
)

This will valid the parameter only if it is included in the set

Valid a range

param(
	[Parameter(Mandatory=$true)]
	[ValidateRange(1, 15)]
	[int]$Limit
)

Only a number between 1 to 15 is accepted

Valid a parameter with code

param(
	[Parameter(Mandatory=$true)]
    [ValidateScript({Test-Path $_ -PathType 'Container'})]
    [string]$MyPath
)

Valid directly that the parameter which should be a path is correct

Valid a parameter is not null

param(
	[ValidateNotNull()]
    [Parameter(Mandatory=$true)]
    [string]$MyPath
)

Check if a parameter is set

if($PSBoundParameters.ContainsKey('MyParam')){
	
}

If the parameter MyParam contains something…

Return values

function Get-MyFunction{

	$Total = 2 + 2

    return $Total
}

$MyInt = Get-MyFunction

You can return a variable with return.

function Get-MyFunction{
	
    $a = "aha"
    $o = "oho"

    return $a, $o
}

$MyArray = Get-MyFunction

You can even return many parameters, you just need to separate them by a comma.

PS C:\> $MyArray
aha
oho

The value is stored in the variable $MyInt in the first example and in $MyArray in the second.

Provide information about your function

function Get-MyFunction{
    <#
		.SYNOPSIS
		In a few words, what my function does
        
		.DESCRIPTION
        Here you can provide more information about what the function does and how
		
		.PARAMETER Param1
		Explain what is param1
        
		.PARAMETER Param2
		Explain what is param2
		
		.EXAMPLE
		Explain here how to run Get-MyFunction
        
		.EXAMPLE
		Get-MyFunction -Param1 "abc" -param2 "efg"        
        
		.NOTES
		FunctionName : ADD-WPLibrary
		Created by   : Yann Greder
		Date Coded   : 2021/03/02 11:00:00
    #>

Approved Verbs for PowerShell Commands/functions

If you use Visual Studio Code and don’t use an approved verb for your function, this going to trigger a warning saying “The cmdlet uses an unapproved verb”. Of course, the code will work just fine. If you want to follow best practices check this official doc. This is to ensure consistency between the cmdlets that you create, the cmdlets that are provided by PowerShell, and the cmdlets that are designed by others.

Examples: Do not use a synonym of an approved verb. For example, always use Remove, never use Delete or Eliminate. But use: New, Set, Add, Get, Read, Invoke, Copy, Open, Remove

Begin, Process, End

function Get-MyFunction{
    <#
		.SYNOPSIS
		
		.DESCRIPTION
	#>

    [cmdletbinding()]
    param(

    )

    BEGIN{
        
    }
    
    PROCESS{
	
    }

    END{
        
    }
}

Run a function with start-job (or Start-ThreadJob) and argument

Function Job1 ($variable) {
    Write-host "Start job1"
    Write-host $variable
}

$Var = "string"

$ExportFunctions = [scriptblock]::Create(@"
    Function Job1 { $function:Job1  } 
"@)

Start-Job -InitializationScript $ExportFunctions -ScriptBlock { Job1 $Using:Var } | Wait-Job | Receive-Job

Function template

function Get-MyTemplate{
    <#
		.SYNOPSIS
		
		.DESCRIPTION
        
        .PARAMETER MyParam
        
        .EXAMPLE
	#>

    [cmdletbinding()]
    param(

    )

    BEGIN{
        
    }
    
    PROCESS{
	
    }

    END{
        
    }
}

1 thought on “Functions in PowerShell – All-in-one”

Leave a Comment