ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【C#】システムログの取得とそこに含まれるEventDataの値を取得する

 過去の記事でシステムログ関連のことをやってきました。

 今回は実際にシステムログを取得してみた記事になります。


 では、始めます。


1:システムログの取得方法
 やり方は色々とありますが、今回は「EventLogReader」を使ったやり方を紹介します。

 やり方は簡単で以下のような方法で取得できます。

// イベントログ取得(EventLogQueryの第一引数にはログ名を設定する。今回はSystemログのため"System"を設定)
EventLogQuery eventLogQuery = new EventLogQuery("System", PathType.LogName);
EventLogReader eventLogReader = new EventLogReader(eventLogQuery);

// 取得したログ全てについての処理
for (EventRecord eventRecord = eventLogReader.ReadEvent(); eventRecord != null; eventRecord = eventLogReader.ReadEvent())
{
    // 1つのログごとに何らかの処理をここに書く
}

 最初の「EventLogQuery eventLogQuery = new EventLogQuery("System", PathType.LogName);」で対象のログを読み込んでいます。
 今回はシステムログを読み込みたかったので第一引数に「"System"」を設定しています。第二引数に「PathType.LogName」を設定することでイベントログの名前が格納されます。
 それをEventLogReaderで読み込み、for文を使ってログを1つずつ抽出している形になります。


2:システムログのEventDataの値を取得する
 前に記事にも書きましたが、システムログの「詳細」タブのEventDataの内容はアプリ毎に自由に設定できるものです。

 そのEventDataの内容へアクセスする場合は、以下のように「EventRecordのProperties」を使います。

// 1の方法でEventRecordを取得してきたという前提
for (EventRecord eventRecord = eventLogReader.ReadEvent(); eventRecord != null; eventRecord = eventLogReader.ReadEvent())
{
    eventRecord.Properties[0].Value; // EventDataの1番目、つまり画像での「TSId」を取得(文字列にするならさらにtoStringが必要)
    eventRecord.Properties[1].Value; // EventDataの2番目、つまり画像での「UserSid」を取得(文字列にするならさらにtoStringが必要)
}

 EventDataの中身はアプリ毎によって全く違うため「存在するか、Propertiesの長さがちゃんとあるか」などチェックしてから取得するようにするのが良さそうです。


3:システムログのログインとログアウトをUserSidから取得するサンプル
 1と2でシステムログの取得とそこに含まれるEventDataの取得方法がわかったので、今までの記事の内容と合わせて「システムログのログインとログアウトをUserSidから取得」してみようと思います。

 前回と同じようにC#のコンソールプロジェクトを作成し、その名前を「コンソールプロジェクト」として以下のプログラムをコピペしてください。

・Program.cs

using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace コンソールプロジェクト
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // SIDを取得
            string myUser = Environment.UserName;
            string userSid = GetUserSid(myUser);
            Console.WriteLine(userSid);

            // SIDのログを取得
            string loginLogout = GetLog(userSid);
            Console.WriteLine(loginLogout);

            Console.ReadKey();
        }

        // ユーザ名からSIDに変換する
        private static string GetUserSid(string username)
        {
            NTAccount nTAccount = new NTAccount(username);
            SecurityIdentifier s = (SecurityIdentifier)nTAccount.Translate(typeof(SecurityIdentifier)); // ユーザが存在しなかった場合ここでエラーになる
            string userSid = s.ToString();
            return userSid;
        }

        // ログを取得する
        private static string GetLog(string userSid)
        {
            // Systemのイベントログ取得
            EventLogQuery eventLogQuery = new EventLogQuery("System", PathType.LogName);
            EventLogReader eventLogReader = new EventLogReader(eventLogQuery);

            StringBuilder sb = new StringBuilder();

            // 取得したログ全てについての処理
            for (EventRecord eventRecord = eventLogReader.ReadEvent(); eventRecord != null; eventRecord = eventLogReader.ReadEvent())
            {
                // ログインとログアウトのイベントIDのみ実行
                if (eventRecord.Id == 7001 || eventRecord.Id == 7002)
                {
                    // ログからSIDを取得して一致判定
                    string logUserSid = GetLogUserSid(eventRecord);
                    if (!userSid.Equals(logUserSid)) continue;

                    // SIDが一致していたら結果に追加
                    sb.Append("Time = ");
                    sb.Append(eventRecord.TimeCreated);
                    sb.Append(", EventID = ");
                    sb.Append(eventRecord.Id);
                    sb.Append(", usersid = ");
                    sb.Append(logUserSid);
                    sb.Append(Environment.NewLine);
                }
            }
            return sb.ToString();
        }

        // ログのUserSIDを取得する
        private static string GetLogUserSid(EventRecord eventRecord)
        {
            string userId = null;
            if (eventRecord.UserId != null && eventRecord.Properties.Count >= 2)
            {
                userId = eventRecord.Properties[1].Value.ToString();
            }
            return userId;
        }
    }
}

 特にプログラムの解説はする必要ないかと思いますが、エラー処理などは不十分だと思うのでしっかりやりたい場合は色々と改造してみてください。

 実行すると以下のように実行したユーザのSIDと一致しているログインとログアウトのログがあれば、そのログの時刻とイベントID、SIDを表示しています。


 以上がC#でシステムログの取得とそこに含まれるEventDataの値を取得する方法になります。

 イベントビューアーにあるEventDataの取得方法がわからなくてかなり長時間悩んだりしたので、同じように困っている人の助けになればと思います。


・参考資料