Get-Eventlogの使い方から覚えていくPowershellの基本的な使い方

# Get-EventLogの使い方から覚えていこう

Powershell を活用したいと思うなら、まず、Windowsのログを確認できる **Get-EventLog** の使い方を覚えるのがいいと思う。このコマンドレットは、使い方を覚えたらすぐに活用できる。また、Powershellの使い方のコツを覚えるのに、非常にやりやすい。

**Get-EventLog** の出力結果を **Select-Object** にパイプで渡してフィルタをかけたり、 **Format-List** や **Format-Table** で表示を変えるたりと、非常に汎用性が高い。GUIでWindows の Log を確認するより、大幅に効率よくログの確認ができるようになる。

また、リモートで他のサーバからログを取得できたり、取得するログの条件を設定できたりと、Windows のコマンドだけではできないような操作を一行で書くこともできる。

# Get-EventLogの基本的な使い方

管理者権限を持つユーザでログインしてPowerShellのプロンプトから以下のコマンドを打ち込んで実行する。

```powershell
↓↓↓↓↓↓↓ あなたの記事の内容
Get-Eventlog -LogName System
───────
Get-EventLog -LogName System
↑↑↑↑↑↑↑ 編集リクエストの内容
```

↓↓↓↓↓↓↓ あなたの記事の内容
**Get-Eventlog** の後に **-LogName** のパラメータに表示するログを指定する。こでだけで、Winndows の System ログがそのまま出力される。Windows のイベントログには何種類かある。**-LogName** の後に **Ctrl + Space** で補完をすると、閲覧できるログの一覧が表示される。
───────
**Get-EventLog** の後に **-LogName** のパラメータに表示するログを指定する。こでだけで、Windows の System ログがそのまま出力される。Windows のイベントログには何種類かある。**-LogName** の後に **Ctrl + Space** で補完をすると、閲覧できるログの一覧が表示される。
↑↑↑↑↑↑↑ 編集リクエストの内容

``` powershell
PS > Get-EventLog -LogName #ここまで入力して Ctrl + Space を入力
Application             Internet Explorer       OAlerts                 System
HardwareEvents          Key Management Service  Security                Windows PowerShell
```

# 最新のLogを表示する

Get-EventLogを実行すると大量のログが出力される。**-Newest** のパラメータをつけると、に指定した個数のログが、新しい順に出力される。

```Powershell
PS C:\Users\Main> Get-EventLog -LogName System -Newest 3

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   22315 1 18 11:52    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22314 1 18 11:49    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22313 1 18 11:48    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
# 最新の3件のログが出力される。
```

# Get-EventLogのパラメータ

**Get-EventLog** で以下のパラメータが使用できる。

```Powershell
PS C:\Users\Main> Get-EventLog -LogName System -ComputerName
ComputerName         InstanceId           AsBaseObject         InformationAction    OutBuffer
Newest               Index                Verbose              ErrorVariable        PipelineVariable
After                EntryType            Debug                WarningVariable
Before               Source               ErrorAction          InformationVariable
UserName             Message              WarningAction        OutVariable
```

**-EntryType** というパラメータを使うと、 エラーやインフォメーションなど出力するログを選ぶことができる。**-EntryType** の後に以下のログの種類を指定すると、指定した種類のログが出力される。

```Powershell
PS > Get-EventLog -LogName System -EntryType #ここでCtrl + Space を入力
Error         FailureAudit  Information   SuccessAudit  Warning
# 指定できるログの種類が表示されるので、矢印で選んで決定し、コマンドレットを実行する。
```

**-Source** や *-Massage* のパラメータも同様に、入力した文字列でフィルタをかけてログを出力する。文字列にはワイルドカードを使用できる。

```Powershell
PS > Get-EventLog -LogName System -Newest 3 -Source ser* #ser* でヒットしたログを表示

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   22315 1 18 11:52    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22314 1 18 11:49    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22313 1 18 11:48    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
```

これらのオプションを使えるようになると、コマンドレットでの出力に対してフィルタをかける感覚が掴めてくる。難しい書き方を覚えなくても、欲しい出力がえられるようになる。

# 時間帯を指定してログを出力する

**Get-EventLog** には **-After** と **-Before** というパラメータがある。これは、時刻を指定して、出力されるログの時間帯をフィルタリングできる。このパラメータの使い方を覚えると、他のコマンドでも時間でのフィルタする方法が分かるようになる。

まず、時刻でログをフィルタする場合は、文字列で`yyyy/MM/DD hh:mm:ss`の形式で日付を指定する。

```powershell
PS C:\Users\Main> Get-EventLog -LogName System -After "2020/01/18 12:00:00"

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   22352 1 18 19:52    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22351 1 18 19:49    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22350 1 18 19:47    Information Service Control M...   1073748864 Background
・
・
・
```

**-after** のパラメータで"2020/01/18 12:00:00"を指定して、"2020/01/18 12:00:00" 以降のログを取得する。ただ、所定の日付や現在の時刻から○日前のようなログを取得したい場合はどうすればいいのだろうか。まず、パラメータに渡した値が文字列なので、**[datetime]**の型を指定して、プロパティで日付を計算する。

```Powershell
PS > ([datetime]"2020/1/18").AddDays(-1)
 #文字列の頭間に"[datetime]"を付けて日時のデータに変換する。
2020年1月17日 0:00:00
```

**Get-Date** で現在の時刻を出力すると、[datetime]の形式でデータが出力される。[datetime]を指定したのと同様に、**.AddDays()*のようなプロパティを使用することができる。書き方を覚えて動かしてみて、その後に仕組を追うと分かりやすい。

```powershell
PS > (get-date).AddDays(-1)
2020年1月17日 20:07:52 #一日先の時刻になる
```

このやり方で日時を指定して、今日の日付で出力されたログをフィルタリングしてみる。

```powershell
↓↓↓↓↓↓↓ あなたの記事の内容
PS > get-eventlog -logName system -after (get-date).AddDays(-1)
───────
PS > Get-EventLog -LogName system -after (get-date).AddDays(-1)
↑↑↑↑↑↑↑ 編集リクエストの内容

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   22353 1 18 19:54    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
   22352 1 18 19:52    Information Service Control M...   1073748864 Background Intelligent Transfer Service サービ...
・
・
・
```

パラメータに **-before** を指定すると、指定した日付より前の日付でデータをフィルタリングする。

# 一般的なコマンドレットでのフィルタリング

**Get-EventLog** のパラメータで出力されるデータのフィルタリングを行ったが、Powershell のコマンドレットの出力は、 **?** を使って以下のような書き方で出力にフィルタをかけることができる。

```powershell
<コマンドレット> | ? { $_.<オブジェクトのメンバー> <演算子> <値> }
```

詳しい説明は省くが、まず使ってみてやり方を覚えておこう。このやり方で **Get-EventLog** の **EntryType** (ログの種類) が **Error** のデータをフィルタリングすると以下のようになる。

```powershell
PS > Get-EventLog -LogName system | ?{ $_.EntryType -eq "Error"}

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   22324 1 18 19:40    Error       ACPI                   3221553165 : 埋め込みコントローラー (EC) が指定されたタイ...
   22219 1 18 11:40    Error       volmgr                 3221487662 クラッシュ ダンプを初期化できませんでした。
・
・
・
```

**?** でフィルタリングをする際に、**$_.** の後に、**Get-EventLog** の出力に含まれるメンバの **EntryType** を指定する。コマンドレットの出力にどのようなメンバが含まれているかは、**Get-Member** のコマンドレットで調べることができる。

```powershell
PS C:\Users\Main> Get-EventLog -LogName system -Newest 1 | Get-Member


   TypeName: System.Diagnostics.EventLogEntry#system/DCOM/10016

Name                      MemberType     Definition
----                      ----------     ----------
Disposed                  Event          System.EventHandler Disposed(System.Object, System.EventArgs)
CreateObjRef              Method         System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose                   Method         void Dispose(), void IDisposable.Dispose()
Equals                    Method         bool Equals(System.Diagnostics.EventLogEntry otherEntry), bool Equals(Syste...
GetHashCode               Method         int GetHashCode()
GetLifetimeService        Method         System.Object GetLifetimeService()
GetObjectData             Method         void ISerializable.GetObjectData(System.Runtime.Serialization.Serialization...
GetType                   Method         type GetType()
InitializeLifetimeService Method         System.Object InitializeLifetimeService()
ToString                  Method         string ToString()
Category                  Property       string Category {get;}
CategoryNumber            Property       int16 CategoryNumber {get;}
Container                 Property       System.ComponentModel.IContainer Container {get;}
Data                      Property       byte[] Data {get;}
EntryType                 Property       System.Diagnostics.EventLogEntryType EntryType {get;} # 今回指定したメンバ
Index                     Property       int Index {get;}
InstanceId                Property       long InstanceId {get;}
MachineName               Property       string MachineName {get;}
Message                   Property       string Message {get;}
ReplacementStrings        Property       string[] ReplacementStrings {get;}
Site                      Property       System.ComponentModel.ISite Site {get;set;}
Source                    Property       string Source {get;}
TimeGenerated             Property       datetime TimeGenerated {get;}
TimeWritten               Property       datetime TimeWritten {get;}
UserName                  Property       string UserName {get;}
EventID                   ScriptProperty System.Object EventID {get=$this.get_EventID() -band 0xFFFF;}
```

フィルタリングする際に使用する演算子は、基本的なもので以下のようなものがある。

|演算子|内容|
|:--|:--|
|-eq|等しいか比較|
|-ne|等しくないか比較|
|-like|ワイルドカードを使ったLike検索にヒットするか|
|-notlike|ワイルドカードを使ったLike検索にヒットしない|
|-gt|より大きいか(>)比較|
|-ge|以上か(>=)比較|
|-lt|より小さいか(<)比較(大文字小文字を区別する)|
-le|以下か(<=)比較(大文字小文字を区別する)|

# メンバーを指定して出力する

Powershellのコマンドレットでは、出力されたオブジェクトのメンバー全ての情報が画面に出力される訳ではない。**Get-Member** のメンバーを全て表示すると以下のようになる。

```powershell
PS > Get-EventLog -LogName System -Newest 1 | Select-Object *


EventID            : 10016
MachineName        : horus
Data               : {}
Index              : 22358
Category           : (0)
CategoryNumber     : 0
EntryType          : Warning
Message            : ソース 'DCOM' のイベント ID '10016' の説明が見つかりません。必要なレジストリ情報またはメッセージを
                     表示するメッセージ DLL ファイルがローカル コンピューターに存在しない可能性があります。または、これ
                     らのデータへのアクセス許可がユーザーに与えられていない可能性があります。次の情報はイベントの一部で
                     す:'コンピューターの既定', 'ローカル', 'アクティブ化', '{C2F03A33-21F5-47FA-B4BB-156362A2F239}', '
                     {316CDED5-E4AE-4B15-9113-7055D84DCC97}', 'HORUS', 'Main', 'S-1-5-21-4290914949-3746008403-17899708
                     94-1001', 'LocalHost (LRPC 使用)', 'Microsoft.Windows.ShellExperienceHost_10.0.18362.449_neutral_n
                     eutral_cw5n1h2txyewy', 'S-1-15-2-155514346-2573954481-755741238-1654018636-1233331829-3075935687-2
                     861478708'
Source             : DCOM
ReplacementStrings : {コンピューターの既定, ローカル, アクティブ化, {C2F03A33-21F5-47FA-B4BB-156362A2F239}...}
InstanceId         : 10016
TimeGenerated      : 2020/01/18 20:38:47
TimeWritten        : 2020/01/18 20:38:47
UserName           : HORUS\Main
Site               :
Container          :
```

**Select-Object** にコマンドレットの出力をパイプで渡すことで、オブジェクトのメンバーを指定して出力することができる。**\*(アスタリスク)** を指定すれば、全てのオブジェクトが出力される。**TimeGenerated** と **EntryType** のメンバーだけを出力したい場合は以下のようにメンバを指定する。

```powershell
PS > Get-EventLog -LogName System -Newest 1 | Select-Object TimeGenerated ,EntryType

TimeGenerated       EntryType
-------------       ---------
2020/01/18 20:38:47   Warning

```

コマンドレットの出力で表示したいメンバーを指定してデータをフィルタリングできれば、欲しいデータを出力できるようになる。コマンドレットの出力から必要な箇所を探すより効率的に確認することができる。

# 表示形式の変更

コマンドレットの出力を **Format-Table** にパイプで渡すと、データがテーブル形式で出力される。**Format-List** に渡すとリスト形式で出力される。

```powershell
PS C:\Users\Main> Get-EventLog -LogName System -Newest 3 | Format-Table

   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   22426 1 19 19:24    Information Microsoft-Windows...           44 Windows Update は更新プログラムのダウンロードを...
   22425 1 19 19:24    Information Microsoft-Windows...           44 Windows Update は更新プログラムのダウンロードを...
   22424 1 19 19:24    Information Microsoft-Windows...           44 Windows Update は更新プログラムのダウンロードを...


PS C:\Users\Main> Get-EventLog -LogName System -Newest 3 | Format-List


Index              : 22426
EntryType          : Information
InstanceId         : 44
Message            : Windows Update は更新プログラムのダウンロードを開始しました。
Category           : (1)
CategoryNumber     : 1
ReplacementStrings : {9NBLGGH3FRZM-Microsoft.VCLibs.140.00, {5f87c2b0-d4fd-4df1-97bf-5a69007f813f}, 1}
Source             : Microsoft-Windows-WindowsUpdateClient
TimeGenerated      : 2020/01/19 19:24:58
TimeWritten        : 2020/01/19 19:24:58
UserName           : NT AUTHORITY\SYSTEM

Index              : 22425
EntryType          : Information
InstanceId         : 44
・
・
・
```

コンソールに表示される形は変わるが、データの内容自体は変わらない。List形式で表示された時に項目が多くなるのは、Table形式で出力されたときに画面に表示されていないメンバーが表示されているため。

Powershellでは、コマンドレットを実行したときに取得したデータが全て画面に出力される訳ではない。出力されたデータを調べる事で、欲しいデータが含まれていることがある。コマンドレットを実行して出力されるのは、結果の文字列ではなく、オブジェクトだ。これが分かると、Powershellの使い方が広がる。