6

我一直在研究一些 PowerShell 脚本,发现有些奇怪。我有一个接受 4 个强制参数的脚本:两个字符串和两个布尔值。

.\[scriptname] [string1] [string2] [bool1] [bool2]

这很好用,我已经检查过它们是否都被正确传递了。

但是,当 PowerShell 要求提供参数时,我发现了一些相当奇怪的东西。它将两个布尔值都设置为 true。

.\[scriptname] [string1] [string2]
please enter bool1: 0
please enter boo2: 0

然后它运行脚本,就好像 bool1 和 bool2 设置为 true,而不是我设置的那样。我对各种不同的东西都有真实的传递,它总是导致真实的。

我不确定为什么会发生这种情况,并且想知道是否有人遇到过这个奇怪问题的原因或解决方案!

我还发现任务计划程序也有类似的问题。设置它

powershell -file [scriptlocation] [string1] [string2] [bool1] [bool2]

例子:

powershell -file "C:\script1.ps1" "c:\fileOne.txt" "c:\folder1" 0 0

两个布尔值都以字符串的形式出现。

4

2 回答 2

15

Jeffrey Snover 的这篇博客提供了一些关于 Powershell 中布尔值行为的见解。下面是一段摘录,他创建了一个简单的函数“test”,根据输入参数返回真或假:

PS> test "0"
TRUE
PS> test 0
FALSE
PS> test 1
TRUE
PS> test 0.0
FALSE
PS> test 0x0
FALSE
PS> test 0mb
FALSE
PS> test 0kb
FALSE
PS> test 0D
FALSE
PS> test 0.00000001
TRUE

“0”是 TRUE,因为它是一个 STRING,它的长度为 1。0 是 FALSE,因为它是一个数字,并且该数字是 0。在 PowerShell 中,任何计算结果为 0 的数字都是 FALSE,每个非零数字都是真的。该示例向您展示了一个浮点零、一个十六进制零、0 兆、0 公斤、0 十进制,有各种各样的零,但对于 PowerShell,它们都计算为 FALSE。

如果没有任何示例代码,很难准确地说出发生了什么,但我们可以说的是 Powershell 不会将您的输入识别为零。也许它是一个字符串?Read-Host如果您曾经获得用户输入,这将是正确的。这是一个例子:

PS C:\> $test = Read-Host "Input"
Input: 0
PS C:\> $test.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS C:\> test $test
TRUE

PS C:\> $test = [Int32]$test
PS C:\> test $test
FALSE

您可以通过使用GetType()相关变量进行检查,修复它可能只是显式转换为所需类型的简单问题。

我阅读你的问题的次数越多——除非我误解了它——这似乎解决了你的问题。特别是在您评论说您一直在“传递各种不同的东西”时,因为任何非零长度字符串在这种情况下都会评估为真。

PS C:\> $anotherTest = "42"
PS C:\> test $anotherTest
TRUE
PS C:\> $anotherTest = [Int32]$anotherTest
PS C:\> test $anotherTest
TRUE

编辑:好吧,既然我知道你的环境是什么,我已经在这个问题上做了更多的工作。首先,我上面告诉你的一切都是真的,所以请不要忽视它。您遇到的问题是布尔类型转换正在以一种不立即明显的方式处理 powershell 强制提示输入。

因此,此代码段存在某些情况:

param
(
    [Parameter(mandatory=$true)][bool]$myBool
)
Write-Host $myBool

使用powershell的强制参数提示而不是在命令行提交变量时会导致如下结果:

PS C:\> .\script.ps1 
cmdlet script.ps1 at command pipeline position 1
Supply values for the following parameters: 
myBool: 0 
True

让我重申一下:在 Powershell 中,所有非空长度的字符串都评估为真。这包括“0”,这包括字符串文字。但问题是什么?我们已经明确地将我们的变量声明为 a bool,所以它应该明白我的意思是 0,对吧?

错误的。当我们将输入设置为提示时,会产生一个相当不幸的情况,即我们期望一个布尔值,或者至少是一个字符串。我们确实最终得到了 bool,但还记得当我们将非空字符串转换为 bool 时会发生什么吗?将类型转换为 bool 将应用于您在提示符处设置的文字输入,它不是数字类型。由于输入的长度为非空,因此布尔转换的计算结果为真。您实际上是在执行此操作:

PS C:\> [bool]$myBool = [bool]"0"
PS C:\> $myBool
True

这样做的最大问题是,由于我们已经将变量转换为布尔值,因此字符串已被消耗,我们只剩下值 1 或 True。所以你的“0”字面上变成了1。我们不能再让0回来了。我们应该做什么?我将列出几个选项:

  • 将变量设置为[int]类型而不是[bool]. bool 转换消耗了“0”字符串并将其变成了 1,那么为什么不使用会这样做的类型呢?Powershell 将数字 0 和 1 理解为真假,因此您可以使用任何数字类型。

输出示例:

param
(
    [Parameter(mandatory=$true)][int]$myBool
)
Write-Host $myBool

PS C:\> .\script1.ps1
cmdlet script1.ps1 at command pipeline position 1
Supply values for the following parameters:
myBool: 0
0
  • 如果您将布尔值用作逻辑开关,请考虑[switch]参数类型。除非您明确设置开关,否则开关始终评估为 false。你不应该以这种方式暴露提示,所以你不会遇到这个问题。更多信息在这里
于 2013-08-29T16:42:31.033 回答
0

如果您的函数不接受布尔参数,这可能解释了为什么会发生这种情况(Hyper Anthony 解释得很好)。

那么,您的脚本是否有 param ([string]x1, [string[x2],[bool]y1,[bool]y2) 类型的声明?在这种情况下,y1 和 y2 将是布尔值,但如果不是,则可能被视为值为 0 的字符串,在这种情况下,它被视为不等于 0 的“0”

于 2013-08-30T22:23:56.063 回答