2

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?

2
  • What's the context? You could possibly make a global, or script scope parameter depending on what the ultimate goal is. Commented Jan 16, 2022 at 0:59
  • 2
    Check out the answer here. Similar question, and one of the posts suggests using Dynamic Parameters to accomplish this, which makes sense. Commented Jan 16, 2022 at 1:03

1 Answer 1

4
  • 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]
Sign up to request clarification or add additional context in comments.

1 Comment

I see, @alazyworkaholic - please see my update.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.