Background
Quick Refresher on Powershell.
Specifically, how to pass arguments to functions by value and by reference.
Outline
- Global Variables
- Declare
- functionName
- [string] $global:functionName = “”;
- Prefix variable name with $global
- [string] $global:functionName = “”;
- functionName
- Declare
- Function
- Get-FunctionName
-
[string]$(Get-PSCallStack)[$StackNumber].FunctionName
-
- Get-FunctionName
- Function
- stringConcatByValueAndReference
- Function Declaration
- stringConcatByValueAndReference([string]$str1, [string]$str2, [ref]$result)
- Input Variables str1 and str2 passed by value
- Output Variable result passed by reference
- stringConcatByValueAndReference([string]$str1, [string]$str2, [ref]$result)
- Set Values
- Global Variable
- functionName
- $global:functionName = Get-FunctionName;
- functionName
- Referenced Variable
- input variables
- accessed by value
- $output = $FORMAT_STRING_COMPOSITION -f $str1, $str2;
- accessed by value
- result
- $result.value = $output;
- input variables
- Global Variable
- Function Declaration
- stringConcatByReferenceIncorrect
- Function Declaration
- stringConcatByReferenceIncorrect([ref] $str1, [ref]$str2, [ref]$result)
- Input Variables ( str1 and str2 ) passed by reference
- Output Variable ( result ) passed by reference
- stringConcatByReferenceIncorrect([ref] $str1, [ref]$str2, [ref]$result)
- Set Values
- Global Variable
- functionName
- $global:functionName = Get-FunctionName;
- functionName
- Referenced Variable
- input variables
- accessed by value
- $output = $FORMAT_STRING_COMPOSITION -f $str1, $str2;
- accessed by value
- result
- $result.value = $output;
- input variables
- Global Variable
- Function Declaration
- stringConcatByReferenceProper
- Function Declaration
- stringConcatByReferenceProper([ref]$str1, [ref]$str2, [ref]$result)
- Input Variables ( str1 and str2 ) passed by reference
- Output Variable ( result ) passed by reference
- stringConcatByReferenceProper([ref]$str1, [ref]$str2, [ref]$result)
- Set Values
- Global Variable
- functionName
- $global:functionName = Get-FunctionName;
- functionName
- Referenced Variable
- input variables
- accessed by reference
- $output = $FORMAT_STRING_COMPOSITION -f $str1.value, $str2.value;
- accessed by reference
- result
- $result.value = $output;
- input variables
- Global Variable
- Function Declaration
- stringConcatByValueAndReference
Code
[string] $str1 = "Joe"; [string] $str2 = "Smith"; [string] $result2 = ""; [string] $log = ""; <# Setting a global PowerShell variable from a function where the global variable name is a variable passed to the function https://stackoverflow.com/questions/12535419/setting-a-global-powershell-variable-from-a-function-where-the-global-variable-n #> [string] $global:functionName = ""; Set-Variable FORMAT_STRING_COMPOSITION -option Constant -value "{0} {1}"; Set-Variable FORMAT_OUTPUT -option Constant -value "Function:- {0}`r`n`r`n`t{1} and {2} yields {3}"; <# Is there a way to retrieve a PowerShell function name from within a function? https://stackoverflow.com/questions/3689543/is-there-a-way-to-retrieve-a-powershell-function-name-from-within-a-function #> function Get-FunctionName ([int]$StackNumber = 1) { return [string]$(Get-PSCallStack)[$StackNumber].FunctionName } <# functionName stringConcatByValueAndReference a) the input variables (str1 and str2) are passed by value b) the output variable is passed by reference c) the content of the result variable is set via the variable value property #> function stringConcatByValueAndReference([string]$str1, [string]$str2, [ref]$result) { [string] $output =""; $global:functionName = Get-FunctionName; $output = $FORMAT_STRING_COMPOSITION -f $str1, $str2; $result.value = $output; } <# functionName stringConcatByReferenceIncorrect a) all variables are passed by reference b) missed accessing the "input" variables via the value property c) the content of the result variable is accessed via the variable value property #> function stringConcatByReferenceIncorrect([ref] $str1, [ref]$str2, [ref]$result) { [string] $output =""; $global:functionName = Get-FunctionName; $output = $FORMAT_STRING_COMPOSITION -f $str1, $str2; $result.value = $output; } <# functionName stringConcatByReferenceProper a) all variables are passed by reference b) the content of each variable is accessed via the variables value property #> function stringConcatByReferenceProper([ref]$str1, [ref]$str2, [ref]$result) { [string] $output =""; $global:functionName = Get-FunctionName; $output = $FORMAT_STRING_COMPOSITION -f $str1.value, $str2.value; $result.value = $output; } Write-Output ""; Write-Output ""; <# Set Variables #> $str1 = "Joe"; $str2 = "Smith"; $result2 = ""; <# Invoke stringConcatByValueAndReference #> stringConcatByValueAndReference -str1 $str1 -str2 $str2 -result ( [ref] $result2 ) $log = $FORMAT_OUTPUT -f $functionName, $str1, $str2, $result2; Write-Output $log; Write-Output ""; Write-Output ""; <# Invoke stringConcatByReferenceIncorrect #> stringConcatByReferenceIncorrect -str1 ( [ref] $str1 ) -str2 ( [ref] $str2 ) -result ( [ref] $result2 ) $log = $FORMAT_OUTPUT -f $functionName, $str1, $str2, $result2; Write-Output $log; Write-Output ""; Write-Output ""; <# Invoke stringConcatByReferenceProper #> stringConcatByReferenceProper -str1 ( [ref] $str1 ) -str2 ( [ref] $str2 ) -result ( [ref] $result2 ) $log = $FORMAT_OUTPUT -f $functionName, $str1, $str2, $result2; Write-Output $log; Write-Output ""; Write-Output ""; <# Undeclared variable:- $result1 fails as a avariable needs to be declared and assigned to be used as a reference argument #> <# stringConcatByReferenceIncorrect -str1 ( [ref] $str1 ) -str2 ( [ref] $str2 ) -result ( [ref] $result1 ) #>
Output
Output- Image
Output- Text
>powershell ./string.concat.ps1 Function:- stringConcatByValueAndReference Joe and Smith yields Joe Smith Function:- stringConcatByReferenceIncorrect Joe and Smith yields System.Management.Automation.PSReference`1[System.String] System.Management.Automation.PSReference`1[System.String] Function:- stringConcatByReferenceProper Joe and Smith yields Joe Smith >
Issues
Pass a variable by reference, but not access it using the value property
Outline
If you access a variable passed by reference, without using the value property.
Code
<# functionName stringConcatByReferenceIncorrect a) all variables are passed by reference b) missed accessing the "input" variables via the value property c) the content of the result variable is accessed via the variable value property #> function stringConcatByReferenceIncorrect([ref] $str1, [ref]$str2, [ref]$result) { [string] $output =""; $global:functionName = Get-FunctionName; $output = $FORMAT_STRING_COMPOSITION -f $str1, $str2; $result.value = $output; }
Output
Output – Image
Output – Textual
Function:- stringConcatByReferenceIncorrect Joe and Smith yields System.Management.Automation.PSReference`1[System.String] System.Management.Automation.PSReference`1[System.String]
Pass an undeclared variable by reference
Outline
If you attempt to pass along an undeclared variable by reference, you will get a telling error.
Code
[string] $str1 = "Joe"; [string] $str2 = "Smith"; [string] $result2 = ""; [string] $log = ""; <# Setting a global PowerShell variable from a function where the global variable name is a variable passed to the function https://stackoverflow.com/questions/12535419/setting-a-global-powershell-variable-from-a-function-where-the-global-variable-n #> [string] $global:functionName = ""; Set-Variable FORMAT_STRING_COMPOSITION -option Constant -value "{0} {1}"; Set-Variable FORMAT_OUTPUT -option Constant -value "Function:- {0}`r`n`r`n`t{1} and {2} yields {3}"; <# Is there a way to retrieve a PowerShell function name from within a function? https://stackoverflow.com/questions/3689543/is-there-a-way-to-retrieve-a-powershell-function-name-from-within-a-function #> function Get-FunctionName ([int]$StackNumber = 1) { return [string]$(Get-PSCallStack)[$StackNumber].FunctionName } <# functionName stringConcatByReferenceIncorrect a) all variables are passed by reference b) missed accessing the "input" variables via the value property c) the content of the result variable is accessed via the variable value property #> function stringConcatByReferenceIncorrect([ref] $str1, [ref]$str2, [ref]$result) { [string] $output =""; $global:functionName = Get-FunctionName; $output = $FORMAT_STRING_COMPOSITION -f $str1, $str2; $result.value = $output; } <# Set Variables #> $str1 = "Joe"; $str2 = "Smith"; $result2 = ""; Write-Output ""; Write-Output ""; <# Invoke stringConcatByReferenceIncorrect #> <# Undeclared variable:- $result1 fails as a avariable needs to be declared and assigned to be used as a reference argument #> stringConcatByReferenceIncorrect -str1 ( [ref] $str1 ) -str2 ( [ref] $str2 ) -result ( [ref] $result1 )
Output
Output – Image
Output – Text
>powershell ./string.concat.referencePassAnUndeclaredVariable.ps1 [ref] cannot be applied to a variable that does not exist. At C:personaldadenijiblogmicrosoftpowershelldatatypestringscenariostring.concatstring.concat.referencePassAnUndeclaredVariable.ps1:73 char:1 + stringConcatByReferenceIncorrect -str1 ( [ref] $str1 ) -str2 ( [ref] ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (result1:VariablePath) [], RuntimeException + FullyQualifiedErrorId : NonExistingVariableReference >
Explanation
The $result1 variable has yet to be declared.
Source Code
GitLab
- Powershell – Function Parameters – By Value And By Reference
https://gitlab.com/-/snippets/2502352 ( Link )- Files
- File Name #1
- Argument passed by referenced ( variable is undeclared )
string.concat.referencePassAnUndeclaredVariable.ps1
- Argument passed by referenced ( variable is undeclared )
- File Name #1
- Files