Reuse parameters among multiple powershell functions
Consider two powershell functions:
function A {
params(
[Parameter()]$x,
[Parameter()]$y
)
Write-Host $x $y
}
function B {
params(
[Parameter()]$x,
[Parameter()]$z
)
Write-Host $x $z
}
I'd like to define a single parameter $x
once (which could have fairly complex attributes that must be kept identical for both functions) and re-use it in both functions, so something like:
$x = {[Parameter()]$x}
function A {
params(
$x,
[Parameter()]$y
)
Write-Host $x $y
}
function B {
params(
$x,
[Parameter()]$z
)
Write-Host $x $z
}
(How) is this possible?
Solution 1:
-
To reuse parameter declarations across functions - as requested in your question - see the following section.
-
To reuse parameter values (arguments) across functions, by way of presets (default value), see the bottom section.
In order to reuse parameter declarations - short of using design-time templating to generate source code - you need to to define a script block that creates a dynamic parameter that can be passed to the dynamicparam
block of multiple advanced functions:
using namespace System.Management.Automation
# The script block that declares the dynamic parameter to be shared
# across functions.
$sharedDynParam = {
# Define the -x parameter dynamically.
$paramName = 'x'
$dict = [RuntimeDefinedParameterDictionary]::new()
$dict.Add(
$paramName,
[RuntimeDefinedParameter]::new(
$paramName,
[datetime], # Type the parameter [datetime]. for instance.
[ParameterAttribute] @{
Mandatory = $true # Make the parameter mandatory, for instance.
# ParameterSetName = 'default' # Assign it to a parameter set, if neeeded.
}
)
)
# Return the dictionary
return $dict
}
function A {
[CmdletBinding()]
param(
$y
)
# Assign the shared dynamic parameter.
dynamicparam { & $sharedDynParam }
# The use of `dynamicparam { ... }` requires use of an explicit
# `process { ... }` block (and optionally `begin { ... }` and
# `end { ... }`, as needed).
process {
# Note: A dynamic -x parameter cannot be accessed as $x
# Instead, it must be accessed via the $PSBoundParameters dictionary.
"[$($PSBoundParameters['x'])] - [$y]"
}
}
function B {
[CmdletBinding()]
param(
$z
)
# Assign the shared dynamic parameter.
dynamicparam { & $sharedDynParam }
process {
"[$($PSBoundParameters['x'])] - [$z]"
}
}
# Sample calls,
A -x '1970-01-01' -y yval
B -x '1970-01-02' -z zval
Output:
[01/01/1970 00:00:00] - [yval]
[01/02/1970 00:00:00] - [zval]
To preset the value of a parameter by a given name across commands, use the $PSDefaultParameterValues
preference variable:
# Preset a parameter value for all commands ('*') that have
# an -x ('x') parameter.
$PSDefaultParameterValues = @{ '*:x' = [pscustomobject] @{ foo = 1; bar = 2 } }
function A {
[CmdletBinding()] # This makes the function an *advanced* one, which respects
# $PSDefaultParameterValues; similarly, at least one
# parameter-individual [Parameter()] attribute does the same.
param(
$x,
$y
)
"[$x] - [$y]"
}
function B {
[CmdletBinding()]
param(
$x,
$z
)
"[$x] - [$z]"
}
# Sample calls, without an -x argument, relying on
# $PSDefaultParameterValues to provide it automatically.
A -y yval
B -z zval
Output, showing that parameter -x
was automatically bound via $PSDefaultParameterValues
:
[@{foo=1; bar=2}] - [yval]
[@{foo=1; bar=2}] - [zval]