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

mut*_*gan 93 powershell scripting

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

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify $false
Run Code Online (Sandbox Code Playgroud)

该命令失败,并显示以下错误:

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
Run Code Online (Sandbox Code Playgroud)

截至目前,我在我的脚本中使用字符串进行布尔转换.但是如何将布尔参数传递给PowerShell?

Dav*_*dro 166

更明确的用法可能是使用开关参数.然后,只有Unify参数的存在意味着它被设置.

像这样:

param (
  [int] $Turn,
  [switch] $Unify
)
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.为了进一步讨论,您可以像任何其他参数一样设置默认值:`[switch] $ Unify = $ false` (19认同)
  • @MarioTacke 如果您在调用脚本时未指定 switch 参数,则它会自动设置为 `$false`。因此无需显式设置默认值。 (2认同)

Emp*_*LII 55

看来powershell.exe在-File使用参数时没有完全评估脚本参数.特别是,$false参数被视为字符串值,与下面的示例类似:

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
Run Code Online (Sandbox Code Playgroud)

而不是使用-File你可以尝试-Command,它会将调用评估为脚本:

CMD> powershell.exe -NoProfile -Command .\RunScript.ps1 -Turn 1 -Unify $false
Turn: 1
Unify: False
Run Code Online (Sandbox Code Playgroud)

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

CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True
Run Code Online (Sandbox Code Playgroud)

  • 对于那些(像我一样)必须保留"-File"参数,并且不能更改为switch参数,但确实可以控制发送的字符串值的人,那么最简单的解决方案是将参数转换为boolean using [System.Convert] :: ToBoolean($ Unify); 字符串值必须为"True"或"False". (6认同)

Fil*_*urt 11

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

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

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

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

用法

.\RunScript.ps1 -Turn 1 -Unity $false
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于-File参数 (8认同)

Lar*_*sWA 9

这是一个较旧的问题,但在PowerShell文档中实际上有一个答案.我有同样的问题,一旦RTFM实际解决了它.几乎.

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

-File参数的文档指出"在极少数情况下,您可能需要为switch参数提供布尔值.要在File参数的值中为switch参数提供布尔值,请将参数名称和值括起来花括号,如下所示:-File.\ Get-Script.ps1 {-All:$ False}"

我不得不这样写:

PowerShell.Exe -File MyFile.ps1 {-SomeBoolParameter:False}
Run Code Online (Sandbox Code Playgroud)

因此,在PowerShell 4.0上,在真/假声明之前没有'$',这对我有用

  • 我很惊讶这种尴尬的解决方法曾经奏效 - 它在 Windows PowerShell v5.1 中不起作用(无论有或没有前导“$”);另请注意,在 PowerShell _Core_ 中不再需要它。我已要求更正文档;请参阅 https://github.com/MicrosoftDocs/PowerShell-Docs/issues/4964 (3认同)

Jan*_*nRK 6

从 bash 在 Linux 上运行 powershell 脚本也会出现同样的问题。解决方法与 LarsWA 的答案几乎相同:

在职的:

pwsh -f ./test.ps1 -bool:true
Run Code Online (Sandbox Code Playgroud)

不工作:

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
Run Code Online (Sandbox Code Playgroud)

  • 这里的情况也一样。这太愚蠢了。 (4认同)

Dra*_*ius 5

我认为,使用/设置布尔值作为参数的最佳方法是在PS脚本中使用,如下所示:

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

$deployAppBool = $false
switch($deployPmCmParse.ToLower()) {
    "true" { $deployAppBool = $true }
    default { $deployAppBool = $false }
}
Run Code Online (Sandbox Code Playgroud)

所以现在您可以像这样使用它:

.\myApp.ps1 -deployAppBool True
.\myApp.ps1 -deployAppBool TRUE
.\myApp.ps1 -deployAppBool true
.\myApp.ps1 -deployAppBool "true"
.\myApp.ps1 -deployAppBool false
#and etc...
Run Code Online (Sandbox Code Playgroud)

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


mkl*_*nt0 5

总结和补充现有的答案,从 Windows PowerShell v5.1(最新也是最后一个版本)/PowerShell(核心)7.3.3 开始:

David Mohundro 的回答正确地指出,您应该在 PowerShell 中使用参数,而不是[bool][switch]参数,其中开关名称的存在与不存在-Unify(指定与指定)意味着它的值,这使得原始问题消失。


但是,有时您可能仍然需要显式传递开关值,特别是当您以编程方式构建命令行时:


PowerShell Core 7+中,原来的问题(在皇帝四十二的回答中描述)已得到修复

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

pwsh -File .\RunScript.ps1 -Unify:$true  # !! ":" separates name and value, no space
Run Code Online (Sandbox Code Playgroud)

可以使用以下值:$falsefalse$truetrue,但请注意传递01不起作用。

请注意开关名称与值如何分隔,并且两者之间:不能有空格。

注意:如果您声明一个[bool]参数而不是 a [switch](通常不应该这样做),则必须使用相同的语法。尽管-Unify $false 应该可以工作,但目前还不能 - 请参阅GitHub 问题 #10838


Windows PowerShell中,最初的问题仍然存在,并且鉴于 Windows PowerShell 不再被积极开发,因此不太可能得到解决

:: # From cmd.exe
powershell -Command "& .\RunScript.ps1 -Unify:$true" 
Run Code Online (Sandbox Code Playgroud)

您可以-Command有效地传递一段PowerShell 代码,然后像往常一样对其进行评估 - 在 PowerShell 内部传递$true$false可以工作(但不是 trueand false,因为现在也接受 with -File)。

注意事项

  • 使用-Command可能会导致对参数进行额外的解释,例如它们是否包含$字符。(其中-File,参数是文字)。

  • 使用-Command可能会导致不同的退出代码

详情请参见这个答案这个答案