トップ回答者
Get-WinEvent (-FilterXPath使用) のTargetUserNameで指定できる数の上限

質問
-
Get-WinEventコマンドの -FilterXPath オプションを使用しています。
以下のように、orまたはandで検索対象とするユーザーを大量に連結させると、存在するはずのログが一つも出力されない結果となります。
ただし、22ユーザーまでなら意図した結果が得られます(すなわち、該当するユーザーのログすべて)。
23を超えると以下のようなメッセージとなります。Get-WinEvent : 指定した選択条件に一致するイベントが見つかりませんでした。 発生場所 行:26 文字:1 + Get-WinEvent -FilterXPath $query + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (:) [Get-WinEvent], Exception + FullyQualifiedErrorId : NoMatchingEventsFound,Microsoft.PowerShell.Commands.GetWinEventCommand
実行例は以下の通りです。以下の場合ですと、上記のような結果になります。
$query = @" Event/EventData[(Data[@Name='TargetUserName']!="z") or (Data[@Name='TargetUserName']!="a") or (Data[@Name='TargetUserName']!="b") or (Data[@Name='TargetUserName']!="c") or (Data[@Name='TargetUserName']!="d") or (Data[@Name='TargetUserName']!="e") or (Data[@Name='TargetUserName']!="f") or (Data[@Name='TargetUserName']!="g") or (Data[@Name='TargetUserName']!="h") or (Data[@Name='TargetUserName']!="i") or (Data[@Name='TargetUserName']!="j") or (Data[@Name='TargetUserName']!="k") or (Data[@Name='TargetUserName']!="l") or (Data[@Name='TargetUserName']!="m") or (Data[@Name='TargetUserName']!="n") or (Data[@Name='TargetUserName']!="o") or (Data[@Name='TargetUserName']!="p") or (Data[@Name='TargetUserName']!="q") or (Data[@Name='TargetUserName']!="r") or (Data[@Name='TargetUserName']!="s") or (Data[@Name='TargetUserName']!="t") or (Data[@Name='TargetUserName']!="u") or (Data[@Name='TargetUserName']!="v") ] "@ Get-WinEvent -FilterXPath $query
これは、コマンドの仕様、またはOSの仕様によるものでしょうか。あるいはFilterXPathの書式の問題でしょうか。
実際には40ユーザほどを指定したいのですが、解決策はありますか。
よろしくおねがいいたします。
OSはWindows7 Professional(b7601 SP1)です。
- 編集済み Fuzitaman 2016年11月8日 1:45
回答
-
Get-WinEventコマンドの制限や、XPath書式の仕様については不明ですが、何らかの制限にかかってしまっている可能性は高いと思います。
XPathの構文で、ある要素を含む時にtrueを返すようなものがあれば良いのですが、私の調べた限りは無かったです。
そこでXPathを諦めて、PowerShellのフィルタで何とかする方法を考えました。
Get-WinEvent| ? { $null -ne (([xml]$_.ToXml()).Event.EventData.Data | ? { $_.Name -eq "TargetUserName" -and @("a","b","c","d","e") -notcontains $_."#text"} ) }
Get-WinEventコマンドはEventLogRecordオブジェクトを返すのですが、ここから直接TargetUserNameというプロパティ名を指定してフィルタをかけることができないので、まずToXml()メソッドでXMLデータに変換しています。
次に、<Event><EventData>ノードを辿り、配下の<Data>ノードのリストを取得。
<Data>ノードのうち、属性名が"TargetUserName"でかつ、その値(#textで取得)に指定のユーザー名が含まれていないものを取得。
↑のデータが一つでも存在すれば($nullでなければ)trueを返します。
あまりスマートではないですが、私はこの方法しか思いつきませんでした。
実際に使うときには、Get-WinEventの-ProviderNameや-FilterXPathなどで取得対象のイベントログをあらかじめ絞ってから、上記のスクリプトに渡してやるといいと思います。
- 回答としてマーク 牟田口大介Moderator 2016年11月8日 21:06
すべての返信
-
Get-WinEventコマンドの制限や、XPath書式の仕様については不明ですが、何らかの制限にかかってしまっている可能性は高いと思います。
XPathの構文で、ある要素を含む時にtrueを返すようなものがあれば良いのですが、私の調べた限りは無かったです。
そこでXPathを諦めて、PowerShellのフィルタで何とかする方法を考えました。
Get-WinEvent| ? { $null -ne (([xml]$_.ToXml()).Event.EventData.Data | ? { $_.Name -eq "TargetUserName" -and @("a","b","c","d","e") -notcontains $_."#text"} ) }
Get-WinEventコマンドはEventLogRecordオブジェクトを返すのですが、ここから直接TargetUserNameというプロパティ名を指定してフィルタをかけることができないので、まずToXml()メソッドでXMLデータに変換しています。
次に、<Event><EventData>ノードを辿り、配下の<Data>ノードのリストを取得。
<Data>ノードのうち、属性名が"TargetUserName"でかつ、その値(#textで取得)に指定のユーザー名が含まれていないものを取得。
↑のデータが一つでも存在すれば($nullでなければ)trueを返します。
あまりスマートではないですが、私はこの方法しか思いつきませんでした。
実際に使うときには、Get-WinEventの-ProviderNameや-FilterXPathなどで取得対象のイベントログをあらかじめ絞ってから、上記のスクリプトに渡してやるといいと思います。
- 回答としてマーク 牟田口大介Moderator 2016年11月8日 21:06