2011-10-02 20 views
5

比較下面的三個腳本:如何使用Get-Process中的Count屬性返回相當零的值?

樣品1

$a = GPS | Where {$_.ProcessName -Match 'AcroRd32'} 
$a 
$a.Count 

If ($a.Count -Eq 0) 
{ 
    Echo "Adobe Reader is Off" 
} 
Else 
{ 
    Echo "Adobe Reader is On" 
} 

# If Adobe Reader is not running, how come 0 (zero) is not returned? 
# This is prettier, should I use it? Or does it slow down performance? 



樣品2

$a = GPS AcroRd32 
$a 
$a.Count 

If ($a.Count -Eq 0) 
{ 
    Echo "Adobe Reader is Off" 
} 
Else 
{ 
    Echo "Adobe Reader is On" 
} 

# If Adobe Reader is not running, how come 0 (zero) is not returned? 
# This is uglier, but it doesn't have to pipe any output, so does it have any performance gains? 



樣品3

GPS AcroRd32 | Measure | Select -Expand Count 

# 0 (zero) is returned, but with an ugly Error 



我想我的問題的一部分是我在處理PowerShell的喜歡它的VBS;以這種方式/樣式編寫代碼通常會產生一個零整數值,並且不會拋出任何錯誤(如果Adobe Reader當然關閉了)。什麼是正確 PowerShell檢查程序實例沒有運行的方式?評論中的性能問題僅次於「PowerShell方式」問題。

P.S.說實話,第三個樣本返回的錯誤信息不會破壞任何東西,它只是醜陋的,所以它沒有超出實際使用,所以我猜真正的問題是我只是一個美學吸引力=^D

回答

8

這是一個常見的PowerShell問題。命令可以返回:

  • 沒有〜空(沒有屬性Count,得到它要麼變空或失敗)
  • 一個對象(也可能有自己的財產Count財產,最困惑的情況下, - 可以返回任何東西,或可能不會擁有它,然後讓Count得到空或失敗)
  • 2+對象數組擁有的財產Count

的解決方案是簡單的。當您確實需要返回對象的計數時,請使用@()運算符。結果總是一個數組,它有屬性Count

# this is always an array 
$result = @(<command returning something or nothing>) 

# this is always a number: 
$result.Count 
+0

的'@()'操作者在組合與第一個樣品的初始變量賦值時它很漂亮和功能 - '$ a = @(GPS |其中{$ _。ProcessName -Match'AcroRd32'})''。爲了滿足迂腐衝動的緣故,我要問,莫非(從'GPS'到'Where'管)美學的努力相比會導致性能下降,只是在做'$ a = @(GPS AcroRd32)'?如果那樣,我意識到這將是微不足道的,並通過我們忽視,但我還是想知道,這樣我就可以把自己少一點無知XD – Stisfa

+1

我測這一個過程「遠」:'@(獲取進程遠)〜約1.6毫秒。 '@(Get-Process | where {$ _。ProcessName -eq'far'})'〜6.8毫秒。根據我的經驗,「Where-Object」和「ForEach-Object」基本上很慢,我在腳本中避免使用它們(在V2.0中這總是可能的)。但是他們在打字的命令行中仍然很方便。 –

+2

順便說一句,如果你用'@(GPS AcroRd32)'去,那麼當這個過程不存在的時候,你應該準備好出現錯誤。如果出現錯誤,它會很慢或者可能會失敗,如果錯誤首選項是* Stop *。爲了避免錯誤,你可以使用這一招:http://stackoverflow.com/questions/4362275/powershell-check-if-item-exists-without-an-error-if-it-doesnt/4364807#4364807。然後'@(GPS [A] croRd32)'應該是最好的表現。 –

2

我會建議你做這樣的事情:

$count = @(get-process | ?{$_.ProcessName -eq "AcroRd32"}).count 

if($count -eq 0){ 

write-host "Adobe Reader is Off" 

} else{ 

write-host "Adobe Reader is On" 

} 

什麼上面所做的是,它迫使返回的對象到一個數組,因此,如果沒有讀者進程在運行,你會得到一個空數組和因此其數量將爲零。當你有進程時,你將它們放在數組中,並且你得到非零計數,上面的代碼將按預期工作。

替代基於樣品2 /樣品3:

$acrobat = gps AcroRd32 -ErrorAction SilentlyContinue 
if($acrobat){ 

    write-host "Adobe Reader is On" 

} else{ 

    write-host "Adobe Reader is Off" 

} 

在上面,我們取消錯誤,如果讀者沒有運行。然後,如果設置了$ acrobat,則說明讀者正在運行。

嫖宿代碼:

當閱讀器沒有運行,$一個被分配什麼,因此$a.Count -eq 0將是錯誤的。當讀者正在運行時,$ a被賦予這些過程對象,並且您獲得$ a.Count爲1或更多,因此再次爲false。所以你會永遠得到讀者的關注。

1

你提到在第三示例中的錯誤 - 你可以通過使用SilentlyContinue ErrorAction隱藏消息:

GPS -ea silentlycontinue AcroRd32 | Measure | Select -Expand Count