2012-01-18 11 views
0

サービスのリストを受け取って次のスニペットを実行する汎用関数を作成しようとしています。 1つの値を送信すると、それが機能し、複数の値を送信しようとすると失敗します。powershellで問題が発生しましたwhere-objectフィルター

これについてもっと詳しく調べる方法はありますか?何か簡単なものがありませんか?

cls 

$host_name = "." 
    #works 
$ary_param = "sql" 
    #fails 
#$ary_param = "sql,ftp" 

$services = @($ary_param) 

$colItems = Get-WmiObject -Class Win32_Service -ComputerName $host_name | 
      Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName | 
      Where-Object{$_.Name -like '*' + $services + '*'} 

$ServiceInfo = @() 

foreach ($objItem in $colItems) 
{  
    $tempServiceInfo = "" | Select Name, DisplayName, State, ProcessID, PriorityClass, StartMode, StartName 

    [string]$tempServiceInfo.Name = $objItem.Name.ToString() 
    [string]$tempServiceInfo.DisplayName = $objItem.DisplayName.ToString() 
    [string]$tempServiceInfo.State = $objItem.State.ToString() 
    [string]$tempServiceInfo.ProcessID = $objItem.ProcessID.ToString() 
    [string]$tempServiceInfo.StartMode = $objItem.StartMode.ToString() 
    [string]$tempServiceInfo.StartName = $objItem.StartName.ToString() 

    $svc_pid = $objItem.ProcessID 
    $priority_class = Get-Process -ComputerName $host_name | Select Id, PriorityClass | Where-Object{$_.Id -eq $svc_pid } 
    [string]$tempServiceInfo.PriorityClass = $priority_class.PriorityClass 

    $ServiceInfo += $tempServiceInfo   
} 

$ServiceInfo | Format-Table 
+0

あなたはそれが 'どこ-Object'フィルタに関連していると思いますか? – JNK

答えて

3

あなたは、配列の部分式にこの呼び出しをラップし、古典的なPowerShellの問題を打つ可能性があります:

 
$colItems = @(Get-WmiObject -Class Win32_Service -ComputerName $host_name | 
       Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName | 
       Where-Object{$_.Name -like '*' + $services + '*'}) 

これはそれではない場合、あなたはあなたのスクリプトが失敗している場所について、より具体的だろうか?

アップデート:私はあなたがまたWhere-Objectで最初にフィルタリングすることで、このコマンドを少し最適化し、その後Select-Objectを実行することができます「あなたは例えば-match演算子を持つ単純な正規表現を使用することを

 
$services = "ftp|sql" 
$colItems = @(Get-WmiObject -Class Win32_Service -ComputerName $host_name | 
       Where-Object{$_.Name -match $services} | 
       Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName) 

を示唆している一般的には。 、それはパイプラインで可能な限り早期にフィルタリングを行うことをお勧めしますすべての

+1

+1 - または '[array] $ colitems = ' – JNK

+0

を指定するこれはそうではありませんでした。もし$ ary_param変数に複数の値を入れると、この行で失敗します:[string] $ tempServiceInfo.Name = $ objItem .Name.ToString() – sqlpadawan

+1

あなたのクエリはほとんど結果を返さない可能性が高いので、その行で失敗します。つまり、$ colItemsに$ nullが代入されます(この '$ colItems -eq $ null'をチェックできます)。その場合、PowerShellのforeachループは$ null値を一度反復してから、ヌル値に対して 'ToString'メソッドを呼び出そうとしますが、失敗するでしょう。 $ colItemsが常に配列であることを確認することで、PowerShellは空の配列を反復処理しないため、これは起こりません。 –

0

まず、あなたは、$ary_param内の値のセットを望ん"sql","ftp"していない"sql,ftp"ような何かを行う場合は - 。後者の場合にはそれだけです文字列。サービスとあなたはあなたがしなければならないかもしれませんが、後者を使用したい:

$services = $ary_param.split(",") 

これは配列です$サービスを確認します。 where-object

、何をやっていることは、このようなものです:

"sql server" -like "*" + $services + "*" 

上記真与え、これは$ary_paramが一つだけの要素を持っている場合であるだろう。

$ services = "sql","ftp"のようなものは、上記をfalseに戻します。

あなたは、パイプのサービスにしたいとあなたはforeachのオブジェクトにやりたいことがあります:あなたはには、Get-WmiObjectコマンドでどこ-オブジェクトを使用して、あなたが直接フィルタリングすることができません必要

$services | %{ 
#logic goes here 
#use $_ to represent each service type and use it in the Where-Object 

} 

注:

Get-WmiObject -Class Win32_Service -Filter "Name LIKE '$_'" -ComputerName $host_name 

また、1つのオブジェクトまたは示唆@Keithヒルのように戻っていないオブジェクト、との問題を回避するために、配列にGet-WmiObject出力を強制する必要があります。

0

もう一つの方法は、その場でWQLフィルタを作成するには、次のようになります。

$services = 'ftp','sql','iis' 
$filter=($services | foreach { "Name LIKE '%$_%'" }) -join ' OR ' 
#$filter 
#Name LIKE '%ftp%' OR Name LIKE '%sql%' OR Name LIKE '%iis%' 

Get-WmiObject -Class Win32_Service -ComputerName $host_name -Filter $filter | ` 
Select-Object Name, DisplayName, State, ProcessID, StartMode, StartName 
関連する問題