Using Local Functions on Remote Computers

30/12/2015 – UPDATE : Scriptblock code changed to better llustrate use of multiple local functions used in combination with other code on the remote system, after feedback from Aleksandar Nikolić &  Tommy Maynard. Thanks guys. 🙂

I came across a situation recently where I needed my remote computers to use some functions that were part of a project I was working on. I wanted to use them in various parts of a scriptblock passed from Invoke-Command. Options with Invoke-Command did not allow for this though. You have the mutial exclusive -file and -scriptblock  parameters.

I prefer to keep my functions as separate files as opposed to their inclusion in a module.Loaded functions are stored within the FUNCTION PowerShell provider, and because of this, cmdlets such as Get-ChildItem can be used with them.

I noticed the Name property of items in FUNCTION: always have the name of the function, and the Definition property the actual code.  To convert this to the exact text of the function as we normally see it, should just require some string concatentation  All we were missing was the word Function, and surrounding braces to create a string equivalent of the function. We’d also add new line characters as well for formatting purposes.

This could be done using the format:

Function {`r`n item.definition `r`n}`r`n

This is the function developed below:

function Get-FunctionString
[Parameter(Mandatory = $true)][System.Array] $Function

[string]$strFunctions = $null
$items = Get-ChildItem Function:\ | Where Name -in $Function

ForEach ($item in $items)
$strFunctions += "Function $($item.Name) { `r`n $($item.Definition) `r`n }`r`n"



It takes as a parameter an array, which is filtered against items provided by the Function PowerShell provider.  Then, the function text itself is comprised and concatenated to a string variable, $strFunctions.

At the beginning of our script, we define a string array containing the names of the functions that we wish to used for use remotely. In the below case, I had functions called Get-ServerList and Confirm-ValidSource.

$functions = @('Get-ServerList','Confirm-ValidSource')

Then, the function we created earlier is invoked to return a string of the text from these functions.

$FunctionString = Get-FunctionString -Function $functions

With this variable defined, I can create a new scriptblock of the string of functions above within the remote session, and then dot source it to make all these functions available.


Invoke-Command -ComputerName $item -ScriptBlock {
    $scriptblock = [System.Management.Automation.ScriptBlock]::Create($using:FunctionString)
    . $scriptblock
    $x = Get-ServerList
    If ($x) 
        ForEach ($obj in $x) 
            $y = Confirm-ValidSource($obj)
            If ($y) 
                Write-Output -InputObject "The server $obj has a valid source"
                Write-Output -InputObject "The server $obj does not have a valid source"

For those of using PowerShell Studio, ensure the array of strings variable ($functions in this case) is defined in globals.ps1, and that for each function part of your project, the property CommandExtension is set to True.

Thanks for reading, and feel free to provide feedback.