I have a script foo.ps1
and a batch file foo.cmd
used to launch the script by double clicking the cmd file in file explorer.
The script accepts a switch parameter, but I don't know how to provide this kind of parameter. Simple parameters are ok.
Foo.ps1:
param(
[Parameter()]
[Switch]$MySwitch,
[Parameter()]
[string]$Name
)
Write-Host "`$MySwitch : $MySwitch, `$Name : $name"
Foo.cmd:
Powershell -noprofile -NonInteractive -file "%~dp0\foo.ps1" -Name "abc"
If I call the script with only "Name", it works. But If I specify MySwitch, it stops to work:
Foo2.cmd:
Powershell -noprofile -NonInteractive -File "%~dp0\foo.ps1" -Name "abc" -MySwitch:$false
The error is:
C:\temp\foo.ps1 : Impossible de traiter la transformation d'argument sur le paramètre «MySwitch». Impossible de convertir la valeur «System.String» en type « System.Management.Automation.SwitchParameter». Les paramètres booléens acceptent seulement des valeurs booléennes et des nombres, tels que $True, $False, 1 ou 0.
+ CategoryInfo : InvalidData : (:) [foo.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,foo.ps1
In Windows PowerShell, there is no way to pass Boolean values when powershell.exe
's
-File
parameter is used - this has has since been corrected in PowerShell (Core) 7+, whose CLI is pwsh.exe
[1].
Use the workaround that JosefZ recommends:
Use of -Command
(-c
) instead of -File
makes PowerShell treat the arguments as PowerShell source code rather than literal arguments, in which case $false
is properly recognized (other CLI parameters omitted for brevity).
powershell -c "& \"%~dp0\foo.ps1\" -Name 'abc' -MySwitch:$false"
Note:
&
, the call operator, must be used to invoke the script file, because its path is quoted.
PowerShell expects embedded "
chars. on the command line to be escaped as \"
(not as `"
or ""
, the way it works inside PowerShell).
-Command
, if you need to embed a verbatim "
inside an embedded \"...\"
string, use `\"
(sic).'...'
instead, to avoid the need for escaping, such a call would break if the expanded directory file path (%dp0
) happens to contain '
chars. itself.For general guidance on when to use -File
vs. -Command
and the different syntax rules that apply, see this answer.
On a conceptual note:
Your code already uses the preferred way to pass Boolean arguments in PowerShell: [switch]
parameters (sometimes called flags).
Switch parameters imply Boolean values: If a given switch - by name only - is specified (-MySwitch
), $true
is implied; if it is absent altogether, $false
is implied. That is, simply omitting -MySwitch:$false
would have solved your problem too.
[bool]
-typed parameters - which invariably require an argument - should be avoided. This post contrasts [bool]
with [switch]
parameters.While (PowerShell-internally) you (always) can pass an explicit value (as you tried with
-MySwitch:$false
, note the required :
separator, a space wouldn't work) - doing so is only required in the following scenarios:
In case you want to pass a Boolean value via a variable whose value is determined programmatically.
In the rare case that a switch defaults to $true
, and you need to override that.
For conceptual reasons, defaulting switch parameters to $true
is best avoided in user code: if necessary, negate the logic of your switch; an example is Write-Host
's -NoNewLine
switch.
However, some of PowerShell's common parameters are switch parameters, which can in effect default to $true
via their preference variable counterparts.
-Confirm
switch parameter: The value of the corresponding $ConfirmPreference
preference variable can make it necessary to pass -Confirm:$false
in order to opt-out of a confirmation prompt, even with $ConfirmPreference
's default value (High
).[1] PowerShell (Core) 7+ supports the following Boolean values when -File
is used: $true
, $false
, true
, false
(and also $null
, but its interpretation differs: scripts (including with -File
) and functions interpret it as $false
, whereas cmdlets interpret it as $true
(!)).
Note that with -Command
- and therefore in all PowerShell code - true
and false
do not work, but 0
and 1
do.
Unfortunately, if you pass an unsupported value, you get the same error message in all scenarios, which in the -File
scenario misleadingly suggests that 0
and 1
work too.