2011-10-02 8 views
5

Porównaj trzy skrypty poniżej:Jak zwrócić całkiem zerową wartość za pomocą właściwości Count z Get-Process?

Sample 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? 



Sample 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? 



Próbka 3

GPS AcroRd32 | Measure | Select -Expand Count 

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



Chyba częścią mojego problemu jest to, że jestem leczenia PowerShell jak to VBS; pisanie kodu w ten sposób/stylu zwykle da mi całkowitą wartość zero i nie będzie powodowało żadnych błędów (oczywiście, jeśli Adobe Reader był wyłączony). Jaki jest skuteczny sposób sprawdzania, czy wystąpienie programu nie jest uruchomione w programie PowerShell? Pytania dotyczące wydajności w komentarzach są drugorzędne w stosunku do pytania "PowerShell Way".

P.S. Szczerze mówiąc, komunikat o błędzie zwrócony przez 3rd Sample nie złamie niczego, jest po prostu brzydki, więc nie jest poza praktycznym użyciem, więc domyślam się, że prawdziwym problemem jest to, że jestem tylko frajerem dla estetyki =^D

Odpowiedz

8

Jest to typowy błąd programu PowerShell.Polecenie może wrócić:

  • Nic ~ zerowa (nie ma właściwość Count, coraz to albo dostaje null lub nie)
  • Pojedynczy obiekt (może to mieć własną nieruchomość Count właściwość, najbardziej kłopotliwe sprawa - może powrócić niczego, albo nie może go mieć, a potem coraz Count dostaje null lub nie)
  • 2+ obiekt array, który ma właściwość Count.

Rozwiązanie to jest proste. Gdy naprawdę potrzebujesz liczby zwróconych obiektów, użyj operatora @(). Wynikiem jest zawsze tablica, która ma właściwość Count.

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

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

The '@()' operatora w połączeniu z pierwszych marek zmienna przypisania pierwszej próbki za jest ładny i funkcjonalny - '$ a = @ (GPS | Where {$ _. ProcessName -Match 'AcroRd32'})'. W celu zaspokojenia pedantycznego pragnienia, muszę zapytać, czy wysiłek na rzecz estetyki (rura od "GPS" do "Gdzie") powoduje pogorszenie wydajności w porównaniu z robieniem '$ a = @ (GPS AcroRd32)'? Gdyby tak było, zdałbym sobie sprawę, że to byłoby maleńkie i pozostało niezauważone przez nas, ale nadal chcę wiedzieć, więc mogę uczynić siebie trochę mniej nieświadomym XD – Stisfa

+1

Zmierzyłem to dla procesu "daleko": '@ (Get-Process far) ~ ~ 1,6 ms. '@ (Get-Process | gdzie {$ _. ProcessName -eq 'far'}) ~ ~ 6.8 msec. Z mojego doświadczenia 'Where-Object' i' ForEach-Object' są w zasadzie bardzo powolne, unikam ich w skryptach (w V2.0 jest to zawsze możliwe). Ale są nadal przydatne w linii poleceń podczas pisania. –

+2

BTW, jeśli użyjesz '@ (GPS AcroRd32)', przygotuj się na błędy, gdy proces nie istnieje. W przypadku błędów będzie powolny lub może się nie powieść, jeśli preferencją błędu jest * Stop *. Aby uniknąć błędów, możesz użyć tej sztuczki: http://stackoverflow.com/questions/4362275/powershell-check-if-item-exists-without-an-error-if-it-doesnt/4364807#4364807. Wtedy '@ (GPS [A] croRd32)' powinno być najlepsze dla wydajności. –

2

proponuję zrobić coś takiego:

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

if($count -eq 0){ 

write-host "Adobe Reader is Off" 

} else{ 

write-host "Adobe Reader is On" 

} 

Co powyższe nie jest to, że zmusza ona zwróconych obiektów do tablicy, więc jeśli nie ma procesów czytnik działa, otrzymasz pustą tablicę i stąd jego liczba będzie równa zeru. A kiedy masz procesy, masz je w tablicy i otrzymujesz niezerową liczbę, a powyższy kod działa zgodnie z oczekiwaniami.

alternatywna podstawie sample2/Sample3:

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

    write-host "Adobe Reader is On" 

} else{ 

    write-host "Adobe Reader is Off" 

} 

W powyższym przykładzie, możemy pominąć błąd, jeśli czytelnik nie jest uruchomiony. Następnie, jeśli ustawisz $ acrobat, wiesz, że czytnik działa.

Obserwacje kodzie:

Kiedy czytelnik nie jest uruchomiony, zostaje przydzielony $ a nic i stąd $a.Count -eq 0 będzie fałszywa. Kiedy czytnik jest uruchomiony, $ a zostaje przypisany do tych obiektów procesu, a otrzymasz $ a.Count jako 1 lub więcej, a więc i ponownie false. Więc zawsze otrzymasz, że czytelnik jest włączony.

1

wspomnieć błąd w trzecim przykładzie - można ukryć wiadomość za pomocą SilentlyContinue ErrorAction:

GPS -ea silentlycontinue AcroRd32 | Measure | Select -Expand Count 
Powiązane problemy