2011年5月11日水曜日

◆dotNET型の出力フォーマット(DotNetTypes.format.ps1xml)

イベントログの一覧は以下のような形で取得できる。

PS>Get-EventLog -List

  Max(K) Retain OverflowAction        Entries Log
  ------ ------ --------------        ------- ---
  20,480      0 OverwriteAsNeeded      30,480 Application
  20,480      0 OverwriteAsNeeded           0 HardwareEvents
     512      7 OverwriteOlder              0 Internet Explorer
  20,480      0 OverwriteAsNeeded           0 Key Management Service
   8,192      0 OverwriteAsNeeded           0 Media Center
     128      0 OverwriteAsNeeded       2,359 OAlerts
  20,480      0 OverwriteAsNeeded      29,732 Security
  20,480      0 OverwriteAsNeeded      58,985 System
  15,360      0 OverwriteAsNeeded      19,325 Windows PowerShell

この結果から、Entriesがゼロのログを除外するには、普通に考えると以下のようになる。

PS>Get-EventLog -List | ?{$_.Entries}

  Max(K) Retain OverflowAction        Entries Log
  ------ ------ --------------        ------- ---
  20,480      0 OverwriteAsNeeded      30,480 Application
     128      0 OverwriteAsNeeded       2,359 OAlerts
  20,480      0 OverwriteAsNeeded      29,732 Security
  20,480      0 OverwriteAsNeeded      58,985 System
  15,360      0 OverwriteAsNeeded      19,325 Windows PowerShell

結果は期待通りのものが取得できているのだが、何かがおかしい。
試してみると分かるがやけに時間がかかるのである。最初の一覧表示がノータイムで帰ってきていることを思えば、そこからEntriesがゼロの4行をフィルターするだけの処理もノータイムで返ってきて然るべき。

そこで、その原因を調べてみた。

PS>Get-EventLog -List | gm Entries


   TypeName: System.Diagnostics.EventLog

Name    MemberType Definition
----    ---------- ----------
Entries Property   System.Diagnostics.EventLogEntryCollection Entries {get;}

これを見ると判るように、そもそもEntriesプロパティは

EventLogEntryCollectionを返してきている。
にも関わらず単純に画面出力したときは、その数が表示されているということはそこに何かが介在していることになる。

PowershellではdotNETのオブジェクトを出力するときにDotNetTypes.format.ps1xmlというファイルの定義に従って表示する仕掛けになっている。(パスは通常C:\WINDOWS\system32\WindowsPowerShell\v1.0)

そこでこの中身を確認してみると

Diagnostics.EventLogクラスは以下のように定義されている。

<View>
    <Name>System.Diagnostics.EventLog</Name>
    <ViewSelectedBy>
        <TypeName>System.Diagnostics.EventLog</TypeName>
    </ViewSelectedBy>

    <TableControl>
        <TableHeaders>
            <TableColumnHeader>
                <Label>Max(K)</Label>
                <Alignment>Right</Alignment>
                <Width>8</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Label>Retain</Label>
                <Alignment>Right</Alignment>
                <Width>6</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Label>OverflowAction</Label>
                <Width>18</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Label>Entries</Label>
                <Alignment>Right</Alignment>
                <Width>10</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Label>Log</Label>
            </TableColumnHeader>

        </TableHeaders>
        <TableRowEntries>
            <TableRowEntry>
                <TableColumnItems>
                    <TableColumnItem>
                        <ScriptBlock>$_.MaximumKilobytes.ToString('N0')</ScriptBlock>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>MinimumRetentionDays</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>OverflowAction</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <ScriptBlock>$_.Entries.Count.ToString('N0')</ScriptBlock>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>Log</PropertyName>
                    </TableColumnItem>

                </TableColumnItems>
            </TableRowEntry>
         </TableRowEntries>
    </TableControl>
</View>

Entriesプロパティは、そのCountを表示する仕掛けになっていることが解る。

そこで先のフィルターを以下のように書き換える。

PS>get-eventlog -List  | ? {$_.entries.count}

  Max(K) Retain OverflowAction        Entries Log
  ------ ------ --------------        ------- ---
  20,480      0 OverwriteAsNeeded      30,480 Application
     128      0 OverwriteAsNeeded       2,359 OAlerts
  20,480      0 OverwriteAsNeeded      29,732 Security
  20,480      0 OverwriteAsNeeded      58,987 System
  15,360      0 OverwriteAsNeeded      19,325 Windows PowerShell

すると期待通り、ノータイムで結果が帰ってきた。(最初のやり方では各Entrieの中身を全件なめて抽出が行われているのだろう)

0 件のコメント:

コメントを投稿