Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass boolean values to a PowerShell script from a command prompt

People also ask

How do you declare a Boolean in PowerShell?

PowerShell Boolean operators are $true and $false which mentions if any condition, action or expression output is true or false and that time $true and $false output returns as respectively, and sometimes Boolean operators are also treated as the 1 means True and 0 means false.

How do you pass a Boolean value to a string?

toString(boolean b): This method works same as String. valueOf() method. It belongs to the Boolean class and converts the specified boolean to String. If the passes boolean value is true then the returned string would be having “true” value, similarly for false the returned string would be having “false” value.

Does PowerShell have Boolean?

PowerShell can implicitly treat any type as a Boolean. It is important to understand the rules that PowerShell uses to convert other types to Boolean values.


A more clear usage might be to use switch parameters instead. Then, just the existence of the Unify parameter would mean it was set.

Like so:

param (
  [int] $Turn,
  [switch] $Unify
)

It appears that powershell.exe does not fully evaluate script arguments when the -File parameter is used. In particular, the $false argument is being treated as a string value, in a similar way to the example below:

PS> function f( [bool]$b ) { $b }; f -b '$false'
f : Cannot process argument transformation on parameter 'b'. Cannot convert value 
"System.String" to type "System.Boolean", parameters of this type only accept 
booleans or numbers, use $true, $false, 1 or 0 instead.
At line:1 char:36
+ function f( [bool]$b ) { $b }; f -b <<<<  '$false'
    + CategoryInfo          : InvalidData: (:) [f], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,f

Instead of using -File you could try -Command, which will evaluate the call as script:

CMD> powershell.exe -NoProfile -Command .\RunScript.ps1 -Turn 1 -Unify $false
Turn: 1
Unify: False

As David suggests, using a switch argument would also be more idiomatic, simplifying the call by removing the need to pass a boolean value explicitly:

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True

Try setting the type of your parameter to [bool]:

param
(
    [int]$Turn = 0
    [bool]$Unity = $false
)

switch ($Unity)
{
    $true { "That was true."; break }
    default { "Whatever it was, it wasn't true."; break }
}

This example defaults $Unity to $false if no input is provided.

Usage

.\RunScript.ps1 -Turn 1 -Unity $false

This is an older question, but there is actually an answer to this in the PowerShell documentation. I had the same problem, and for once RTFM actually solved it. Almost.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe

Documentation for the -File parameter states that "In rare cases, you might need to provide a Boolean value for a switch parameter. To provide a Boolean value for a switch parameter in the value of the File parameter, enclose the parameter name and value in curly braces, such as the following: -File .\Get-Script.ps1 {-All:$False}"

I had to write it like this:

PowerShell.Exe -File MyFile.ps1 {-SomeBoolParameter:False}

So no '$' before the true/false statement, and that worked for me, on PowerShell 4.0


I think, best way to use/set boolean value as parameter is to use in your PS script it like this:

Param(
    [Parameter(Mandatory=$false)][ValidateSet("true", "false")][string]$deployApp="false"   
)

$deployAppBool = $false
switch($deployPmCmParse.ToLower()) {
    "true" { $deployAppBool = $true }
    default { $deployAppBool = $false }
}

So now you can use it like this:

.\myApp.ps1 -deployAppBool True
.\myApp.ps1 -deployAppBool TRUE
.\myApp.ps1 -deployAppBool true
.\myApp.ps1 -deployAppBool "true"
.\myApp.ps1 -deployAppBool false
#and etc...

So in arguments from cmd you can pass boolean value as simple string :).


Running powershell scripts on linux from bash gives the same problem. Solved it almost the same as LarsWA's answer:

Working:

pwsh -f ./test.ps1 -bool:true

Not working:

pwsh -f ./test.ps1 -bool=1
pwsh -f ./test.ps1 -bool=true
pwsh -f ./test.ps1 -bool true
pwsh -f ./test.ps1 {-bool=true}
pwsh -f ./test.ps1 -bool=$true
pwsh -f ./test.ps1 -bool=\$true
pwsh -f ./test.ps1 -bool 1
pwsh -f ./test.ps1 -bool:1

To summarize and complement the existing answers, as of Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

David Mohundro's answer rightfully points that instead of [bool] parameters you should use [switch] parameters in PowerShell, where the presence vs. absence of the switch name (-Unify specified vs. not specified) implies its value, which makes the original problem go away.


However, on occasion you may still need to pass the switch value explicitly, particularly if you're constructing a command line programmatically:


In PowerShell Core, the original problem (described in Emperor XLII's answer) has been fixed.

That is, to pass $true explicitly to a [switch] parameter named -Unify you can now write:

pwsh -File .\RunScript.ps1 -Unify:$true  # !! ":" separates name and value, no space

The following values can be used: $false, false, $true, true, but note that passing 0 or 1 does not work.

Note how the switch name is separated from the value with : and there must be no whitespace between the two.

Note: If you declare a [bool] parameter instead of a [switch] (which you generally shouldn't), you must use the same syntax; even though -Unify $false should work, it currently doesn't - see this GitHub issue.


In Windows PowerShell, the original problem persists, and - given that Windows PowerShell is no longer actively developed - is unlikely to get fixed.

  • The workaround suggested in LarsWA's answer - even though it is based on the official help topic as of this writing - does not work in v5.1

    • This GitHub issue asks for the documentation to be corrected and also provides a test command that shows the ineffectiveness of the workaround.
  • Using -Command instead of -File is the only effective workaround:

:: # From cmd.exe
powershell -Command "& .\RunScript.ps1 -Unify:$true" 

With -Command you're effectively passing a piece of PowerShell code, which is then evaluated as usual - and inside PowerShell passing $true and $false works (but not true and false, as now also accepted with -File).

Caveats:

  • Using -Command can result in additional interpretation of your arguments, such as if they contain $ chars. (with -File, arguments are literals).

  • Using -Command can result in a different exit code.

For details, see this answer and this answer.