2011-10-02 5 views
5

は、下の3つのスクリプトの比較: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 



私は私の問題の一部は、それがVBSだように、私はPowerShellを処理することだということだと思います。この方法/スタイルでコードを書くと、通常はゼロの整数値が返され、エラーは発生しません(Adobe Readerがオフの場合)。 の内容プログラムのインスタンスが実行されていないことをPowerShellがチェックする方法はありますか?コメントのパフォーマンスに関する質問は、「PowerShell Way」の質問に続くものです。

P.S.正直言って、3番目のサンプルから返されたエラーメッセージは何も壊れませんでした。ちょうど醜いので、実用的な使い方ではないので、私は本当の問題は私が美学のための吸盤にすぎないと思うことです。^

答えて

8

これは一般的なPowerShellの問題点です。コマンドが返すことができます:

  • ナッシング〜ヌル(プロパティCountを持っていない、それはnullを取得しますか失敗するかのいずれかの取得)
  • 単一のオブジェクト(それは、独自のプロパティCount性を有していてもよい、最も混乱ケース - 何かを返すことができる、またはそれを持っていない可能性があります。Countがnullになるか、失敗します)
  • 2+オブジェクト配列のプロパティはCountです。

解決策は簡単です。返されたオブジェクトの数が本当に必要な場合は、@()演算子を使用します。結果は常に、配列Countを持つ配列です。

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

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

最初のサンプルの最初の変数の代入可能との組み合わせで '@()'演算子それはきれいで機能的です - '$ a = @(GPS | Where {$ _。ProcessName -Match 'AcroRd32'})'。懐疑的な衝動を満たすために、私は質問する必要があります。美学のための努力( 'GPS'から' Where'へのパイプ)は '$ a = @(GPS AcroRd32)'と比較して性能低下を引き起こしますか?もしそれがあったとしても、私はそれが非常に小さく、われわれに気付かれないことに気づいていますが、私はまだ分かりませんので、私は自分自身を少し無知にすることができますXD – Stisfa

+1

私はこれを '遠い'プロセスについて測定しました: '@ ) '〜1.6 msec。 '@(Get-Process | {$ _。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/SAMPLE3に基づい

代替:リーダーが実行されていない場合、上記で

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

    write-host "Adobe Reader is On" 

} else{ 

    write-host "Adobe Reader is Off" 

} 

、我々は、エラーを抑制する。次に、$ acrobatが設定されている場合、リーダーが動作していることがわかります。あなたのコードの

観察:

読者が実行されていない場合は、$ aが何も割り当てられないますので、$a.Count -eq 0はfalseになります。読者が動いているとき、$ aにそれらのプロセスオブジェクトが割り当てられ、$ a.Countが1以上になるので、再びfalseになります。だからあなたはいつも読者がいることを知っているでしょう。

1

あなたは第三の例ではエラーに言及 - あなたはSilentlyContinueというerrorActionというを使用してメッセージを非表示にすることができます:

GPS -ea silentlycontinue AcroRd32 | Measure | Select -Expand Count 
関連する問題