Named Parameters not working as expected
-
lundi 23 mai 2011 13:36Hi,Using PowerShell 2.0At start of script .\PsMyScript.ps1Param{[string]$p1,[string]$p2,[string]$p3}Call the script - works as expected..\PsMyScript.ps1 -p2 "two" -p3 "three" -p1 "one"Call the script - NOT working as expected.\PsMyScript.ps1 "one" "two" "three"The problem is that the parameters are still being populated even though Ididn't supply their names. I'd like to force the parameters to be NAMEDparameters, but I don't need them to be mandatory.
Toutes les réponses
-
lundi 23 mai 2011 13:59
Try using - Position.
Param ( [parameter(Position=0)] [String[]] $p1 )
get-help about_Functions_Advanced_Parameters
-
lundi 23 mai 2011 14:50"Kazun" wrote in messagenews:fc48f2fe-9e2a-4395-aff7-7954915439af@communitybridge.codeplex.com...> Try using - Position.>> Param ( [parameter(Position=0)] [String[]] $p1 )>> get-help about_Functions_Advanced_ParametersThanks, I did read about_Functions_Advanced_Parameters, but didn'tunderstand it.Are you saying to use [parameter(Position=0)] for all parameters? I thoughtit was forcing a positional parameter, which sounded like the opposite towhat I wanted...
-
lundi 23 mai 2011 14:57
No for all:Param( [parameter(Position=0)] [string]$p1, [parameter(Position=1)] [string]$p2, [parameter(Position=2)] [string]$p3 )
-
lundi 23 mai 2011 15:30"Kazun" wrote in messagenews:6f5c009f-0688-4b39-aabb-3dcb4218c064@communitybridge.codeplex.com...> No for all:> Param(> [parameter(Position=0)]> [string]$p1,> [parameter(Position=1)]> [string]$p2,> [parameter(Position=2)]> [string]$p3> )So it looks like I'm forcing them to be positional, but I'd like to be ableto call them in any order, as long as the names are correct. e.g..\PsMyScript.ps1 -p2 "two" -p3 "three" -p1 "one"
-
lundi 23 mai 2011 15:46
Then show on a concrete example of what is not working?"Kazun" wrote in messagenews:6f5c009f-0688-4b39-aabb-3dcb4218c064@communitybridge.codeplex.com...> No for all:> Param(> [parameter(Position=0)]> [string]$p1,> [parameter(Position=1)]> [string]$p2,> [parameter(Position=2)]> [string]$p3> )So it looks like I'm forcing them to be positional, but I'd like to be ableto call them in any order, as long as the names are correct. e.g..\PsMyScript.ps1 -p2 "two" -p3 "three" -p1 "one" -
mardi 24 mai 2011 09:39Thanks for the help. The goal is to only set a parameter when it's name hasbeen specified on the command line. This doesn't seem to be working.#PsTest.ps1param([parameter(position=0)][string]$p1,[parameter(position=1)][string]$p2,[parameter(position=2)][string]$p3)write-host p1 : $p1write-host p2 : $p2write-host p3 : $p3Now call it with three unamed params.\PsTest.ps1 two one threeIn my test, the params will be populated, even though I didn't supply theirnames! I want to force the caller to use this notation..\PsTest.ps1 -p2 two -p1 one -p3 threeFurther to this, the documentation seems wrong. It statesabout_Functions_Advanced_ParametersPosition Named Argument"If this argument is NOT specified, the parameter name or its alias MUST beexplicitly specified when the parameter is set".This implies that there's no way the param can be populated unless you'venamed it?
-
mardi 24 mai 2011 11:04
You may use old style as in the others language is parse $args.
Example for C++ - http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
-
mardi 24 mai 2011 12:20"Kazun" wrote in messagenews:0b5ee9d4-3691-4059-aea2-1d11fbbed197@communitybridge.codeplex.com...> You may use old style as in the others language is parse $args.>> Example for C++ - http://msdn.microsoft.com/en-us/library/17w5ykft.aspxThanks, but I was hoping the new facilities in PowerShell 2.0 would haveeverything needed for accurate passing of parameters. No one has actuallyconfirmed whether my test script is behaving as expected, or whether thedocumentation is correct (see above).
-
mardi 24 mai 2011 13:02ModérateurWhy would you want to do that?
By nature all parameters are positional even if not explicitly declared as such.
This allows you to specify just the arguments (values will bound to the respective parameters by the order they were written on the command line).
You cannot disable positional parameter binding or force the command to accept only parameters that were specified by their names.
Can you clarify your needs?
Shay Levy [MVP]
PowerShay.com
PowerShell Toolbar -
mardi 24 mai 2011 13:04from: get-help about_Functions_Advanced_Parameters<#Position Named ArgumentThe Position argument specifies the position of the parameter.If this argument is not specified, the parameter name or itsalias must be explicitly specified when the parameter is set.Also, if none of the parameters of a function have positions,the Windows PowerShell runtime assigns positions to each parameterbased on the order in which the parameters are received.#>That last sentence about the runtime assignment of positions iswhat is complicating creating the scenario of making all parametersto a script be named only.
-
mardi 24 mai 2011 13:15You can come close to requiring all parameters to be named,but apparently you are required to allow for at least onepositional parameter.Consider for example,param([parameter(Position=0)]$first, $a, $b);$first;$a;$bas the content of test.ps1Then you getC:..\WindowsPowerShell> test.ps1 0 1 2C:\Documents and Settings\Larry\My Documents\WindowsPowerShell\test.ps1: A positional parameter cannot be found that accepts argument '1'.C:..\WindowsPowerShell> test.ps1 0 -a 1 2C:\Documents and Settings\Larry\My Documents\WindowsPowerShell\test.ps1: A positional parameter cannot be found that accepts argument '2'.C:..\WindowsPowerShell> test.ps1 0 -a 1 -b 2012
-
mardi 24 mai 2011 13:25"Shay Levi [MVP]" wrote in messagenews:175101bd-56b3-4f88-8ac8-dd4f8caf5061@communitybridge.codeplex.com...> Why would you want to do that?> By nature all parameters are positional even if not explicitly declared as> such.> This allows you to specify just the arguments (values will bound to the> respective parameters by the order they were written on the command line)..\PsMyScript.ps1 -p2 "two" -p1 "one" -p3 "three" # good.\PsMyScript.ps1 "two" "one" "three" # not good!Why do I want to force named parameters? Because it's a good way ofpreventing mistakes made by the caller. Microsoft use it in their owncommand line tools (Vista and above). e.g. the Tasklist command does notaccept positional parameters. In WSH you can do this. I'd be surprised ifit's not possible in PowerShell.> You cannot disable positional parameter binding or force the command to> accept only parameters that were specified by their names.>> Can you clarify your needs?> --------------------------------------------------------------------------------> Shay Levy [MVP]> PowerShay.com> PowerShell Toolbar
-
mardi 24 mai 2011 13:41Modérateur
You'll have to implement it yourself, here's an example
function Test-NamedParameters
{
Param(
[string]$p1,
[string]$p2,
[string]$p3
)
$p = [System.Management.Automation.PsParser]::Tokenize($MyInvocation.Line,[ref]$null) | ? {$_.Type -match 'CommandParameter|CommandArgument'} | group type -NoElement
$hash = @{}
if($p) { $p | foreach {$hash[$_.Name]=$_.Count} }
# disable calling the function without any parameters
if(!$hash.CommandParameter -and !$hash.CommandArgument)
{
Write-Error "no parameters nor arguments were found"
return
}
if($hash['CommandParameter'] -ne $hash['CommandArgument'])
{
Write-Error "parameter count doesn't match argument count"
return
}
$p1
$p2
$p3
}
Test-NamedParameters #not allowed
Test-NamedParameters -p1 one two three #not allowed
Test-NamedParameters -p1 one -p2 two -p3 three #works
Test-NamedParameters -p2 two -p3 three -p1 one #works
Test-NamedParameters -p3 three #works
Shay Levy [MVP]
PowerShay.com
PowerShell Toolbar -
mardi 24 mai 2011 13:55
You can do something like this in your script:
param(
$bad_param,
[string]$p1,
[string]$p2,
[string]$p3
)if ($bad_param){write-host "Bad parameter";exit}
Any unnamed parameter will get picked up by $bad_param.
[string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "
- Modifié mjolinorMicrosoft Community Contributor mardi 24 mai 2011 15:07
- Proposé comme réponse jrich jeudi 26 mai 2011 12:53
- Marqué comme réponse Alan ZhuModerator vendredi 27 mai 2011 03:25
-
mardi 24 mai 2011 14:43Good idea (but did you mean to code parenthesis insteadof braces in the param block?)
-
mardi 24 mai 2011 14:58Didn't mean to (copied from the OPs original post).
[string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " " -
mardi 24 mai 2011 15:21
-
mercredi 25 mai 2011 19:52mjolinor wrote:> Didn't mean to (copied from the OPs original post).Oops. Sorry about that. I'm used to typing curly brackets in PowerShell.> --------------------------------------------------------------------------------> [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775> 0645570").substring(($_*2),2))})-replace " "
-
mercredi 25 mai 2011 22:35This reminds me of a PowerShell inconsistency.Parentheses and commas are used for both ways that are provided toassociate formal parameters with functions in PowerShell, yet when youcall that function, you do not use parentheses to wrap the list ofactual parameters. For example:function args_form1($a1, $a2){ '>'+$a1+'<';'>'+$a2+'<'}function args_form2{param($a1, $a2);'>'+$a1+'<';'>'+$a2+'<'}args_form1 1 2>1<>2<args_form1(1, 2)>1 2<><args_form2 1 2>1<>2<args_form2(1, 2)>1 2<><Perhapsfunction args_form1 $a1 $a2 { '>'+$a1+'<';'>'+$a2+'<'}function args_form2{param $a1 $a2; '>'+$a1+'<';'>'+$a2+'<'}would have been better as the starting point for the argumentdeclaration syntax. Oh well; it is what it is.On 5/25/2011 2:52 PM, Gerry Hickman wrote:> Oops. Sorry about that. I'm used to typing curly brackets in PowerShell.
-
jeudi 26 mai 2011 06:40Modérateur
-
mercredi 1 juin 2011 08:51"mjolinor" wrote in messagenews:cf01c476-1831-4270-b462-ac7612240a56@communitybridge.codeplex.com...> You can do something like this in your script:>> param(> $bad_param,> [string]$p1,> [string]$p2,> [string]$p3> )>> if ($bad_param){write-host "Bad parameter";exit}>> Any unnamed parameter will get picked up by $bad_param.Thanks, this is a good work-around!
-
lundi 19 septembre 2011 18:18Modérateur
FYI
http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2011/09/19/how-to-disable-positional-parameter-binding-in-powershell.aspx
Shay Levy [MVP]
PowerShay.com
PowerShell Toolbar

