Why is the value of "switch" type parameter passed to a string parameter? Why is the value of "switch" type parameter passed to a string parameter? powershell powershell

Why is the value of "switch" type parameter passed to a string parameter?


@PetSerAl already indicated what your misunderstanding is, but maybe it was a bit too brief, so I'll elaborate a little more.

A [switch] parameter doesn't take a value like regular parameters. You normally set it to true or false respectively by providing or omitting the parameter:

PS C:\> Get-Content .\test.ps1Param(    [string]$Content = $null,    [switch]$Flag)$flag.IsPresent$ContentPS C:\> .\test.ps1FalsePS C:\> .\test.ps1 -FlagTrue

Alternatively you can explicitly pass a value by putting a colon between switch parameter and value:

PS C:\> .\test.ps1 -Flag:$falseFalsePS C:\> .\test.ps1 -Flag:$trueTrue

Whitespace after the colon is allowed, but not before (-Flag: $false passes $false as the switch value, -Flag :$false doesn't).

If you try to assign the switch value without the colon the value is actually passed to the next parameter in line, in your case the -Content parameter:

PS C:\> .\test.ps1 -Flag $falseTrue         # value of the parameter $FlagFalse        # value of the (positional) parameter $ContentPS C:\> .\test.ps1 -Flag -Content $falseTrue         # value of the parameter $FlagFalse        # value of the (named) parameter $Content

If you use -Flag $true (without the colon) and pass a value to the (named) parameter -Content the value $true is passed as an unnamed third parameter (accessible via the automatic variable $args), same as if you put the value at the end of the statement:

PS C:\> Get-Content .\test2.ps1Param(    [string]$Content = $null,    [switch]$Flag)$flag.IsPresent$Content$args[0]PS C:\> .\test2.ps1 -Flag $false -Content 'something'TruesomethingFalse        # $false passed as unnamed 3rd parameterPS C:\> .\test2.ps1 -Flag:$false -Content 'something'False        # $false passed as explicit value of switch parameter $FlagsomethingPS C:\> .\test2.ps1 -Flag -Content 'something' $falseTruesomethingFalse        # $false passed as unnamed 3rd parameter


Give this test code a run, calling it as you did in the question. Add this test:

C:\Users\powershell> .\test.ps1 -flag

Script will illustrate the following points:

  • As per 4c74356b41's comment, switches are $false unless specified on the command line. So -flag sets the $flag switch to true; -flag $true sets the flag to true and passes the argument $true to content.
  • From this, no need to specify $flag=$false in script params
  • Added a test so that you can see when $content is empty/null as there is also no need for $content=$null

param(    [string]$content,    [switch]$flag)$test = [string]::IsNullOrEmpty($content)Write-Output "content: $content"Write-Output "flag   : $flag"Write-Output "Is content null: $test"


I will add to this that you can assign the value via splatting as well, changing the value via the splat parameter assignment from $true to $false will alter your switch 'detection'. This is useful when you are using another value or property to determine if a switch should be used or not.

function FooBar {    param (        [switch]        $Foo    )    if ($Foo){        "Foo"    }    else{        "Bar"    }}$splat = @{    Foo = $False}FooBar @splat