2013-08-29 159 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

相關問題