Jokru
Jokru

Reputation: 69

Use param but save $args in powershell

I'm trying to have a script update itself, and then relaunch itself.

The problem occurs when the script tries to pass parameters to itself, as apparently using param clears $args. I had an idea to make a custom $args-handler that works like param, but is there a better way? I do need the arguments to be named so some handling is necessary, I can't just use $args.

param(
    $a = "abc",
    $b,
    $c
)

Write-Host $a
Write-Host $b
Write-Host $c

Write-Host $args

This results in the following:

.\a.ps1 -a 1 -b 2 3
1
2
3

Writing the $args to host returns nothing.

Upvotes: 1

Views: 1240

Answers (3)

Maximilian Burszley
Maximilian Burszley

Reputation: 19684

Taking your problem statement:

I'm trying to have a script update itself, and then relaunch itself.

This is the purpose of the $PSBoundParameters automatic variable:

.\myscript.ps1 @PSBoundParameters

And your other issue:

when the script tries to pass parameters to itself, as apparently using param clears $args

This is untrue. The issue in your example is positionally-bound parameter binding in action. What actually happens is the 3 gets bound to $c. $args will capture unbound parameters unless you have a parameter with the ValueFromRemainingArguments attribute. You can stop this binding from occurring by using the CmdletBinding attribute:

function Verb-Noun {
    [CmdletBinding(PositionalBinding = $false)]
    param(

As @mklement0 points out, you cannot use $args in advanced functions, where you're using CmdletBinding or Parameter attributes, like my example above.


Docs:

about_Automatic_Variables#args

about_Functions_CmdletBindingAttribute

about_Functions_Advanced_Parameters

Upvotes: 5

iRon
iRon

Reputation: 23763

If you do not need to change the values of the parameters, you might just fetch the arguments from the raw command line:

Write-Host ($MyInvocation.Line -split '\.ps1[\s\''\"]\s*', 2)[-1])

(Or just re-invoke the whole command line in once, but you will need to prevent an infinitive loop somehow)

Upvotes: 0

FoxDeploy
FoxDeploy

Reputation: 13547

$args are only available for the unbound parameters you pass into your script. Once you start binding params, each param you pass in to your script will be bound based on its value, type or position. Anything not matching your param binding will end up in $args

Let's say I have a script like this

#$args.ps1
write-host "args value 1 : $($args[0]) "
write-host "args value 2 : $($args[1]) "

When I call it, I can index into $args and pull the values out.

& C:\temp\args.ps1 'SomeValue1' 'SomeValue2'
args value 1 : SomeValue1 
args value 2 : SomeValue2 

However, once I bind params, $args will then only contains values which don't match your bindings. Notice that only the third param I pass in below ends up in $args

param($param1, $param2)
write-host "params value 1 : $($param1) "
write-host "params value 2 : $($param2) "

write-host "args value 1 : $($args[0]) "
write-host "args value 2 : $($args[1]) "

Now you'll some interesting behavior when I pass in additional params here.

& C:\temp\args.ps1 'SomeValue1' 'SomeValue2' 'SomeValue3'
params value 1 : SomeValue1 
params value 2 : SomeValue2 
args value 1 :  SomeValue3
args value 2 :  

why is it this way?

Think about it like this: as we can see in the help under get-help about_automatic_variables, $args is provided to map the undeclared parameters passed into a script. The second you begin declaring parameters, you are specifically describing which params your script will use, and $args becomes a bit weird in usage.

$Args Contains an array of the undeclared parameters and/or parameter values that are passed to a function, script, or script block. When you create a function, you can declare the parameters by using the param keyword or by adding a comma-separated list of parameters in parentheses after the function name.

*thanks @LotPings for the correction on the behavior of $args, I originally posted in error that $args contians nothing if you bind params.

Upvotes: 1

Related Questions