Ohad Schneider
Ohad Schneider

Reputation: 38152

Using the PowerShell call (&) operator to call PowerShell scripts with switch parameters

Suppose we have the following SwitchTest.ps script

param(
    [switch]$Flag = $false
)

echo "Flag: $Flag"

The following works as expected:

& ".\SwitchTest.ps1" -Flag
Flag: True

However this doesn't

& ".\SwitchTest.ps1" "-Flag"
Flag: False

Furthermore, if we modify SwitchTest.ps to look like this:

param(
    [switch]$Flag = $false,
    [string]$Str = $null
)

echo "Flag: $Flag"
echo "Str: $Str"

We get this expected behavior:

& ".\SwitchTest.ps1" -Flag
Flag: True
Str: 

And this unexpected one:

& ".\SwitchTest.ps1" "-Flag"
Flag: False
Str: -Flag

I tried -Flag true, -Flag $true, -Flag:$true... no cigar. It looks like the switch param is "skipped" when quoted (i.e. when it's a proper string) - why? What do I do if I want to build "-Flag" programmatically?

Upvotes: 2

Views: 5046

Answers (3)

Josh Castillo
Josh Castillo

Reputation: 81

Your asking a very good question and have set up a very good test case. Let's leave flag without a parameter so it defaults to $Null. When you specify -Flag by itself, PowerShell uses the switch paramater. But, PowerShell interprets "-Flag" as a string and therefore tries to find a parameter that matches a string variable and passes that string (including the - because it is in double quotes) to the parameter that matches [String] type. Lastly, since you sent a string "-Flag" to the string variable, the Flag variable was left to its default value which was $Null or $False. Nice question.

Here's your code you can use to test this out.

#Put this in a script file, e.g. ParamTest.ps1
Flag: False
Str: -Flag

param(
    [switch]$Flag,
    [string]$Str = $null
)

Write-Output "Flag: $Flag"
Write-Output "Str: $Str"

Execute just as you did above:

 & ".\SwitchTest.ps1" "-Flag"

But now that you see how PowerShell assigns passed in parameters, try the following to trigger the Flag parameter as you intended were originally intending to do:

& .\ParamScript.ps1 "-Flag" -Flag

Upvotes: 4

Matt
Matt

Reputation: 46730

Forgive me if I am off-base, but if you want to have that flag conditionally set, drop the call operator and just use splatting.

PS M:\Scripts> $params = @{Flag=$true;Str="Bagels"}

PS M:\Scripts> .\switchTest.ps1 @params
Flag: True
Str: Bagels

Upvotes: 3

briantist
briantist

Reputation: 47862

The behavior you're seeing is exactly what I would expect.

If you want to build it programmatically, use Invoke-Expression.

Upvotes: 1

Related Questions