2013-08-29 114 views
5

我一直在研究一些PowerShell脚本,发现有点奇怪。 我有一个接受4个必须参数的脚本:两个字符串和两个布尔值。为什么我的值为0的布尔值返回true?

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

这工作得很好,而且我已经检查它们都被正确传递。

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

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

然后运行脚本,就好像bool1和bool2设置为true,而不是我设置的那样。我真的会传递各种不同的东西,而且总是会成真的。

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

我也发现Task Scheduler有类似的问题。 与

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

例子进行设置:

的powershell -file “C:\ script1.ps1”, “C:\ fileOne.txt”, “C:\文件夹1” 0 0

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

+3

请发布显示此行为的源 – Eris

+0

它并不真正与我的源代码有关,因为我所做的只是将它们作为强制参数传递给它们。 其模拟脚本的其余部分发生了什么。 – Hazz22

+1

希望你现在可以看到发布你的代码的好处。这样做似乎并不直接相关,但它为我们提供了重要的上下文,能够重现您的问题并尽快为您提供帮助。 :) –

回答

13

This blog作者:Jeffrey Snover提供了一些关于布尔运算符在Powershell中的行为的见解。下面是摘录,他在那里创建了一个简单的功能“测试”,以返回true或false取决于输入参数:

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”是正确的,因为它是一个字符串,它的长度为1. 0是 FALSE,因为它是一个数字,该数字是0.在PowerShell中,任何计算为0的 数字都是FALSE,每个非零数字是 TRUE。该示例显示了一个浮点数零,一个十六进制数 零,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中,所有非空长度的字符串评估为true。这包括“0”,这包括字符串文字。但是问题是什么?我们已经明确声明我们的变量为bool,所以它应该明白我的意思是0,对吧?

错误。当我们将输入设置为提示时,会出现一个相当不幸的情况,那就是我们期待bool或至少一个字符串。我们确实最终摆脱了bool,但记住当我们将它们转换为bools时非空字符串会发生什么?将类型转换为bool将应用于在提示中设置的文字输入,该输入不是数字类型。由于输入的长度非空,因此布尔转换的计算结果为true。你基本上是执行此操作:

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

这个最大的问题是,既然我们已经转换我们的变量为布尔,字符串已经被消耗掉,我们只是留下了值1,或真正。所以你的“0”字面上变成1.我们不能再回到0了。我们应该做什么?我将列出几个选项:

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

实施例与输出:

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。你不应该以这种方式暴露提示,所以你不会遇到这个问题。更多信息here
+1

对不同类型的输入的很好的解释。 – Mitul

+0

感谢您的解释。但是,这并不完全回答我的问题。 我在问的是为什么它会从命令行接受0和1变为true和false,但是当它要求命令时,它会判定它们是真的? – Hazz22

+0

命令行和cmdlet之间的区别在于命令行足够智能,可以隐式解释您的输入 - 另一方面,cmdlet具有严格的返回类型。如果我知道您使用的cmdlet,我可以进一步评论,但看起来像Read-Host。在Read-Host上检查[本文档](http://technet.microsoft.com/en-us/library/hh849945.aspx),即使您输入数字值,输出也是System.String。您需要明确地将该字符串“强制转换”为某种数字类型,例如int,以便了解您的意思是0而不是“0”。 –

0

如果你的函数不接受boolean参数,这可能解释为什么会发生这种情况(Hyper Anthony解释得很好)。那么,你的脚本是否有param([string] x1,[string [x2],[bool] y1,[bool] y2)声明类型?在这种情况下,y1和y2将是布尔值,但如果不是可能会被视为值为0的字符串,在这种情况下,它会被视为“0”,而不等于0

+0

所有必需的参数都已明确设置,这使得这有点奇怪。我稍后会发布一些示例代码,以展示我的意思。 – Hazz22

相关问题