如何从命令提示符传递布尔值到 PowerShell 脚本

我必须从批处理文件调用 PowerShell 脚本。脚本的一个参数是一个布尔值:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify $false

命令失败,出现以下错误:

Cannot process argument transformation on parameter 'Unify'. 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:0 char:1
+  <<<< <br/>
+ CategoryInfo          : InvalidData: (:) [RunScript.ps1], ParentContainsErrorRecordException <br/>
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,RunScript.ps1

到目前为止,我在脚本中使用一个字符串来布尔转换。但是如何将布尔参数传递给 PowerShell 呢?

244563 次浏览

更明确的用法可能是使用开关参数。然后,仅仅是统一参数的存在就意味着已经设置了它。

像这样:

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

尝试将参数类型设置为 [bool]:

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


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

如果未提供输入,此示例将 $Unity默认为 $false

用法

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

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

不要使用 -File,你可以尝试使用 -Command,它会以脚本的形式计算调用:

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

正如 David所建议的那样,使用 switch 参数也会更加惯用,通过消除显式传递布尔值的需要来简化调用:

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

你也可以对 False使用 0,对 True使用 1:

无法处理参数“统一”上的参数转换。无法将值 "System.String"转换为类型 "System.Boolean",此类型的参数只能接受布尔值或数字,请使用 $true$false1或0代替。

要了解更多信息,请查看 布尔值和运算符上的这篇 MSDN 文章。

这是一个老问题,但是在 PowerShell 文档中实际上有一个答案。我也遇到过同样的问题,这一次 RTFM 真正解决了这个问题。差不多了。

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

File 参数的文档指出 ”在极少数情况下,您可能需要为开关参数提供一个布尔值。若要在 File 参数的值中为开关参数提供布尔值,请将参数名称和值放在大括号中,如下所示:-File。拿剧本。Ps1{-全部: $False }”

I had to write it like this:

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

所以在 true/false 语句之前没有’$’,这对我来说很有用,在 PowerShell 4.0上

我认为,使用/设置布尔值作为参数的最好方法是在 PS 脚本中这样使用:

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


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

现在你可以这样使用它:

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

因此,在 cmd 的参数中,可以将布尔值作为简单的字符串:)传递。

To 总结和补充 the existing answers, as of Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:

David Mohundro's answer rightfully points that 在 PowerShell 中,应该使用 < a href = “ https://Learn.microsoft.com/en-us/PowerShell/module/microsoft.PowerShell.core/about/about _ function _ Advanced _ properties # switch-properties”rel = “ nofollow noReferrer”> ABC1 properties 来代替 [bool]参数, where the presence vs. absence of the switch name (-Unify specified vs. not specified) implies its value, which makes the original problem go away.


但是,有时您可能仍然需要显式地传递 switch < em > value ,特别是如果您正在构造一个命令行 程序化:


在 PowerShell 核心 中,original problem(在 Emperor XLII's answer中描述) 已被修复

也就是说,要显式地将 $true传递给名为 -Unify[switch]参数,现在可以编写:

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.

注意交换机名称是如何与 :值分开的,并且两者之间必须有 没有空格

注意: 如果声明的是 [bool]参数而不是 [switch](通常不应该声明 [switch]) ,则必须使用相同的语法; 即使 -Unify $false 应该可以工作,它目前也不能-参见 GitHub 的问题


Windows PowerShell中,由于 Windows PowerShell 不再积极发展,原来的问题仍然存在不太可能得到修复。

  • LarsWA 的回答中建议的变通方法——尽管在撰写本文时它是基于 官方帮助的话题的——在 v5.1中可以使用 没有

    • 这个 GitHub 问题 要求更正文档,并提供一个测试命令来显示解决方案的无效性。
  • 使用 -Command而不是 -File是唯一有效的解决办法 :

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

With -Command you're effectively passing a 一段 PowerShell 代码, which is then evaluated as usual - and inside PowerShell passing $true and $false works (but 没有 true and false, as now also accepted with -File).

Caveats:

  • 使用 -Command可能会导致对参数的额外解释,比如它们是否包含 $字符。(对于 -File,参数是 字面意思)。

  • Using -Command can result in a 不同的出口密码.

有关详细信息,请参阅 这个答案这个答案

在 PowerShell 中,可以通过在变量之前提及布尔参数的类型来声明布尔参数。

    function GetWeb() {
param([bool] $includeTags)
........
........
}

可以通过传递 $true | $false 来赋值

    GetWeb -includeTags $true

我在使用调用命令将脚本传递给函数时也遇到了类似的情况。我用单引号代替双引号运行该命令,因为这样它就变成了字符串文字。'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';

在 linux 上从 bash 运行 powershell 脚本也会出现同样的问题,解决方法和 LarsWA 的答案几乎一样:

工作:

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

不起作用:

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

根据我的测试,默认值规范不适用于函数中预期为布尔值的参数。

您可以使用[ switch ]类型,或者如果您真的想使用 boolean,您应该在函数的开始指定默认值,如下所示:

Function nullRules {
Param
(
[Parameter(Mandatory=$false)] $boolWins


)
if ([DBNull]::Value.Equals($boolWins)) {$boolWins=$false}
....
....
}