1

Is there a way to specify parameters for all functions in a Powershell module in one go or does one need to parameterize each function individually ?

Function Get-PhysicalDisk {[cmdletbinding()] param($computername,$credential) get-WmiObject win32_physicalmedia @PSBoundParameters}

Function Get-uptime {[cmdletbinding()] param($computername,$credential) Get-WmiObject Win32_OperatingSystem @PSBoundParameters}

NB: Not marking code as 'code' since I need to highlight the repetitions I want to get rid of.

3
  • @alroc I had highlighted the repetitions I want to get rid of. One cannot highlight anything if it's marked as code. Commented Jun 14, 2014 at 1:06
  • You're free to revert the edit. I marked it as code because it's code, and your "highlights" make the code invalid. You did not indicate why you had done such a thing. Commented Jun 14, 2014 at 1:07
  • You can use default parameter values (predefined variables). But this is not quite possible if you use PSBoundParameters in functions. PSBoundParameters assumes that these parameters are specified explicitly. Commented Jun 14, 2014 at 5:07

2 Answers 2

1

I doubt there's a "built-in" way. If you're determined, I can think of a way to do it, though whether it's a good way is highly questionable. You could assign the repeated declarations to a string, then interpolate that string into strings containing the function definitions, and use Invoke-Expression to define the functions from those strings. Example:

RepeatedParamBlockTest.psm1

$declarations = @'
  [CmdletBinding()]
  param(
    [parameter(Mandatory = $true, Position = 0)] [Alias('Egg', 'Yung')] [string]$Foo,
    [parameter(Mandatory = $true, Position = 1, HelpMessage = "Bar must be a multiple of 5")] [Alias('Rod', 'Beam')] [ValidateScript({$_ % 5 -eq 0})][int]$Bar
  )
'@

Invoke-Expression ("
  function DisplayParams {
    $declarations" + @'

    # This function displays the values of the parameters Foo and Bar
    Write-Host
    Write-Host "Foo: $Foo"
    Write-Host "Bar: $Bar"
  }
'@)

Invoke-Expression ("
  function MultiplyParams {
    [CmdletBinding()]
    $declarations" + @'

    # This function multiplies the values of the parameters Foo and Bar and returns the result
    Write-Verbose "Multiplying '$Foo' by '$Bar'..."
    $multiplied = $Foo * $Bar
    return $multiplied
  }
'@)

If you have many functions, you can streamline this by using a foreach loop instead of separate iex statements:

$declarations = @'
  [CmdletBinding()]
  param(
    $foo,
    $bar
  )
'@

foreach ($functiondef in $(
  ("
    function DisplayParams {
      $declarations" + @'

      # This function displays the values of the parameters Foo and Bar
      Write-Host
      Write-Host "Foo: $Foo"
      Write-Host "Bar: $Bar"
    }
'@),

  ("
    function MultiplyParams {
      $declarations" + @'

      # This function multiplies the values of the parameters Foo and Bar and returns the result
      Write-Verbose "Multiplying '$Foo' by '$Bar'..."
      $multiplied = $Foo * $Bar
      return $multiplied
    }
'@)
  )) {
  Invoke-Expression $functiondef
}

Note the following:

  • '@ must always be at the beginning of the line (no indentation)
  • '@) at the end of each function definition string is followed by a comma for all except the last one, because these strings form an array in the expression part of the foreach loop.

Console session demonstrating that this works:

06-13-14 19:43:31.18 C:\Data Files\scratch\so» Import-Module .\RepeatedParamBlockTest.psm1
06-13-14 20:03:28.56 C:\Data Files\scratch\so» DisplayParams -Foo 'bar' -Bar 8
DisplayParams : Cannot validate argument on parameter 'Bar'. The "$_ % 5 -eq 0" validation script for the argument with value "8" did not return true. Determine why the validation script failed and then try the command again.
At line:1 char:31
+ DisplayParams -Foo 'bar' -Bar 8
+                               ~
    + CategoryInfo          : InvalidData: (:) [DisplayParams], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,DisplayParams

06-13-14 20:03:39.07 C:\Data Files\scratch\so» DisplayParams -Foo bar

cmdlet DisplayParams at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Bar: !?
Bar must be a multiple of 5
Bar: 25

Foo: bar
Bar: 25
06-13-14 20:03:52.73 C:\Data Files\scratch\so» MultiplyParams _ 50
__________________________________________________
06-13-14 20:04:22.78 C:\Data Files\scratch\so»

It's not something that's likely to be implemented as a feature because I really don't think there's much demand for a "clean" way to do something like this rather than just copying and pasting the parameter list. How often does anyone define a significantly large number of functions with identical parameters? I suppose it wouldn't hurt to allow using a splatted array as a parameter list (as I noted in a comment on another answer, AFAIK there currently isn't any way to use an array), but it would be of very limited value.

In any case, it's an interesting question from an academic perspective. I'm curious whether anyone will come up with a better way to do it.


I used generic code and more complex parameter definitions to make it more reproducible for other readers and better demonstrate the proof of concept, but per the OP's request I'm adding an example using his code:

$declarations = @'
  [CmdletBinding()]
  param(
    $computername,
    $credential
  )
'@

foreach ($functiondef in $(
  ("
    function Get-PhysicalDisk {
      $declarations" + @'

      Get-WmiObject win32_physicalmedia @PSBoundParameters
    }
'@),

  ("
    function Get-Uptime {
      $declarations" + @'

      Win32_OperatingSystem @PSBoundParameters
    }
'@)
  )) {
  Invoke-Expression $functiondef
}
Sign up to request clarification or add additional context in comments.

2 Comments

Part 1 of this blog mentions 'Command metadata' as a feature to provide structure to Powershell functions. But I couldn't find an example of it anywhere.
Could you please write the answer with the code I put in the question. It'll be easier for me to understand.
0

This can be done using a technique called splatting, where your parameters are prepared using a hash table.

To get more information how to do it from the help, run the command

Get-Help about_Splatting

1 Comment

Can you give an example? I'm not aware of a way to provide a splatted array as the parameter list. AFAIK splatting can only be used to provide a list of arguments to a command (as indicated by the error message you receive if you use the spatting operator in any other context). Perhaps you misunderstood the question? Unless the OP confused the terminology, he's not asking how to provide the same arguments to each function, he's asking how to define the same set of parameters in each of several functions without repeating the parameter list.

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.