LoginSignup
0
0

More than 5 years have passed since last update.

Powershell2.0でハマッたCountプロパティの使い方

Last updated at Posted at 2017-09-25

Powershell2.0でハマッたCountプロパティの使い方

「プロセスが1個しかない場合Get-Processの数を数えようとして失敗します! どうしましょう!?」という相談があったので、対応をまとめました。

状況

 以下のような状況のとのこと。(プロセスは適当に1個のものでテスト)

問題の環境(Powershell2.0)
PS C:\> (Get-Process -ErrorAction 0 | select MainModule | findstr -i "dwm.exe").Count
PS C:\>         ←応答を返さない

最新バージョンで再現するかどうか?

「まずバージョンを確認して、古かったら上げてみよう」。試してみたところそれなりのバージョンならきちんとプロセス数が返ってきます。

Powershell5.1ならきちんと返ってくる
PS C:\> (Get-Process -ErrorAction 0 | select MainModule | findstr -i "dwm.exe").Count
1       1を返す

暫定対応

 とはいえ、諸般の事情からすぐバージョン上げられない…ということで調べてみたところ、以下のやり取りがヒット。

 コマンドレットの出力が一つの場合は、配列ではなく単一のオブジェクトとして返却されます。
 その場合出力されるオブジェクトは配列ではないので、countプロパティが存在せず、値を返しません。
 この問題の対処方法はコマンドレットの出力に@()をつけることです。1

 試してみたところうまくいきました。

問題の環境(Powershell2.0)
PS C:\> @(Get-Process -ErrorAction 0 | select MainModule | findstr -i "dwm.exe").Count
1       1を返す
PS C:\> 

 @()のメンバをみてみると、Count = Lengthと定義されています。このように定義されているため、@()をつけてやるとCountが使えるようです。2

@()のメンバ
PS C:\> Get-Member -InputObject @() -View Extended

   TypeName: System.Object[]

Name  MemberType    Definition
----  ----------    ----------
Count AliasProperty Count = Length

 Powershell2.0依存の話ではないですが、パイプラインを使って大量のオブジェクトを渡してCountすると遅くなるという事象も。こちらはSystem.Linq.Enumerable を使うことで処理時間を短縮させることが可能です(参考文献が詳しい)。3

 Windows7環境下だと最初からPowershell2.0が入っていて、そのままシェルが動いてしまうからなかなかバージョン違いに気付かなかったりしますが、なるべく最新のバージョンを用意しておいたほうがよいですね。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0