1

Note that the example code is contrived and is meant for illustration of the problem only.

I wanted to make a function in powershell to get some random numbers but i'm running into the very weird issue that when i dont use the position defining of the paramater i still get a error about it.

My code is:

function select-random {

  param(
    [Parameter(Position = 0, Mandatory)]
    [int]$min,
    [Parameter(Position = 1, Mandatory)]
    [int]$max
  )

  Get-Random $min $max

}

The error this script gets with the command: select-random 5 10

A positional parameter cannot be found that accepts argument '10'.

And with the command: select-random -min 5 -max 10

A positional parameter cannot be found that accepts argument '10'.`

The weirdest thing is that the ISE detects the manualy defined paramater in the tab menu.

Is my syntax wrong or is it a powershell bug but mainly how do i fix this?

mklement0
  • 382,024
  • 64
  • 607
  • 775
smvd
  • 117
  • 2
  • 11
  • 3
    You define the parameters as `[int]`, but treat them as strings (`""`)... Also, the `Minimum` parameter is **Named** only, while the first positional parameter should be`Maximum`. Best name both parameters on `Get-Random` – Theo Jan 06 '21 at 16:49
  • 3
    Read the error message carefully: _**Get-Random** : A positional parameter cannot be found_… Use `get-random -Minimum $min -Maximum $max` at line # 11. – JosefZ Jan 06 '21 at 16:59

1 Answers1

1

Theo and JosefZ have provided the crucial pointers in the comments on the question:

You're trying to pass both the $min and $max arguments positionally to Get-Random, yet Get-Random supports only one positional argument, namely for the -Maximum parameter.

Thus, at least the $min value must be passed as a named argument, i.e. as -Minimum $min for your command to work syntactically. However, for symmetry and readability it is better to pass $max as a named argument as well:

# Use *named* arguments.
Get-Random -Minimum $min -Maximum $max

How to determine a command's positional arguments:

The about_Command_Syntax conceptual help topic describes the notation used in PowerShell's so-called syntax diagrams.

To display the syntax diagrams (only), use Get-Command -Syntax (or pass -? / use Get-Help, which shows additional information):

PS> & { Get-Command -Syntax $args[0] } Get-Random

Get-Random [[-Maximum] <Object>] [-SetSeed <int>] [-Minimum <Object>] [-Count <int>] [<CommonParameters>]

Get-Random [-InputObject] <Object[]> -Shuffle [-SetSeed <int>] [<CommonParameters>]

Get-Random [-InputObject] <Object[]> [-SetSeed <int>] [-Count <int>] [<CommonParameters>]

Only parameters whose names alone are enclosed in [...][1] are positional - e.g. [-Maximum] - and, if multiple ones are supported, they are listed in the order in which they must be passed on invocation.

Note that each output line represents a separate parameter set (see about_Parameter_Sets), but since you're passing a minimum and maximum value, only the first one is of interest here:

As you can see, only -Maximum is positional in the first parameter set, -Minimum and all the other parameters are not.


Here's helper function Get-PositionalParameter, which makes it easier to determine a command's positional parameters:

Function Get-PositionalParameter {
<#
.SYNOPSIS
Outputs a given command's positional parameters, if any.
#>
  param(
    [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
    [string] $Name
  )
  Set-StrictMode -Version 1; $ErrorActionPreference = 'Stop'
  # Resolve the name to a cmdlet first, if necessary
  $cmd = (Get-Command $Name)
  if ($cmd.ResolvedCommand) { $cmd = $cmd.ResolvedCommand }

  $cmd.ParameterSets | ForEach-Object {
    if ($posParams = $_.Parameters.Where( { $_.Position -ge 0 })) {
      [pscustomobject] @{
        PositionalParams = $posParams.Name
        ParameterSet     = $_.Name
      }
    }
  }
}

Applied to Get-Random:

PS> Get-PositionalParameter Get-Random

PositionalParams ParameterSet
---------------- ------------
Maximum          RandomNumberParameterSet
InputObject      ShuffleParameterSet
InputObject      RandomListItemParameterSet

Note that the parameter set names do not surface in the help topics and when you use Get-Command -Syntax, because they aren't really meant for public display, but their names are usually descriptive enough to infer their purpose.


[1] Contrast this with the parameter specification as a whole being enclosed in [...] - e.g. [-Minimum <Object>] - which independently indicates that the parameter as a whole is optional (not mandatory, i.e. passing an argument is not required).

mklement0
  • 382,024
  • 64
  • 607
  • 775