首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 讀取 Windows 事件日誌完整指南:EventLog 與 EventLogEntry 深度解析

     編輯:關於C#

前言

Windows 事件日誌 記錄系統、應用程式與安全性相關事件,是系統監控、故障診斷與安全稽核的關鍵資料來源。.NET Framework 提供 System.Diagnostics.EventLog 與 EventLogEntry 類別,讓 C# 開發者能輕松讀取、篩選、監控事件日誌。本文詳細解析核心類別、屬性、方法與實務範例。

核心類別架構

EventLog 類別 (System.Diagnostics)

代表單一事件日誌 (如 Application、System、Security),提供讀寫、監控功能。

屬性/方法說明
Log取得/設定日誌名稱 (Application、System、Security、自訂日誌)
Source取得/設定事件來源名稱 (寫入時需註冊)
MachineName取得/設定目標電腦名稱 (預設為本機 ".")
Entries取得 EventLogEntryCollection,包含所有日誌項目
WriteEntry()寫入事件日誌
Clear()清除日誌 (需管理員權限)
DeleteEventSource()刪除事件來源註冊

EventLogEntry 類別

代表單一事件日誌記錄,唯讀物件,包含豐富的事件中繼資料。

屬性型別說明
EntryTypeEventLogEntryType事件類型:Error、Warning、Information、SuccessAudit、FailureAudit
EventIDint應用程式定義的事件識別碼
Sourcestring產生事件的來源名稱
Messagestring完整的本地化事件訊息
TimeGeneratedDateTime事件產生的本地時間
TimeWrittenDateTime事件寫入日誌的本地時間
MachineNamestring產生事件的電腦名稱
UserNamestring相關使用者帳號 (可能為空)
Categorystring事件類別文字
Databyte[]事件相關的二進位資料

EventLogEntryType 列舉

值說明典型用途
Error錯誤事件,嚴重問題 (功能失效、資料遺失)應用程式崩潰、磁碟故障
Warning警告事件,潛在問題磁碟空間不足、連線逾時
Information資訊事件,成功操作服務啟動、使用者登入
SuccessAudit成功稽核,安全存取成功成功登入、檔案存取
FailureAudit失敗稽核,安全存取失敗登入失敗、權限不足

實務範例 1:讀取系統日誌並篩選錯誤事件

using System;
using System.Diagnostics;
using System.Linq;

public class EventLogReader
{
    /// 
    /// 讀取指定日誌近期的錯誤事件
    /// 
    public static void ReadRecentErrors(string logName = "System", int maxCount = 50)
    {
        using (EventLog eventLog = new EventLog(logName))
        {
            // 由新到舊排序 (Entries 索引 0 為最舊)
            var entries = eventLog.Entries.Cast<EventLogEntry>()
                .Where(e => e.EntryType == EventLogEntryType.Error)
                .OrderByDescending(e => e.TimeGenerated)
                .Take(maxCount);

            Console.WriteLine($"=== {logName} 日誌 - 最近 {maxCount} 筆錯誤事件 ===");
            foreach (var entry in entries)
            {
                Console.WriteLine($"時間: {entry.TimeGenerated:yyyy-MM-dd HH:mm:ss}");
                Console.WriteLine($"來源: {entry.Source}");
                Console.WriteLine($"事件 ID: {entry.EventID}");
                Console.WriteLine($"訊息: {entry.Message}");
                Console.WriteLine(new string('-', 60));
            }
        }
    }

    /// 
    /// 統計各類型事件數量
    /// 
    public static void StatisticEventTypes(string logName = "System")
    {
        using (EventLog eventLog = new EventLog(logName))
        {
            var stats = eventLog.Entries.Cast<EventLogEntry>()
                .GroupBy(e => e.EntryType)
                .Select(g => new { Type = g.Key, Count = g.Count() })
                .OrderByDescending(x => x.Count);

            Console.WriteLine($"=== {logName} 日誌事件類型統計 ===");
            foreach (var stat in stats)
            {
                Console.WriteLine($"{stat.Type,-15} : {stat.Count,6} 筆");
            }
        }
    }
}

實務範例 2:即時監控日誌新增事件 (EventLogWatcher 模式)

using System;
using System.Diagnostics;

public class EventLogMonitor
{
    private EventLog _eventLog;
    private bool _isMonitoring;

    public void StartMonitoring(string logName = "Application", string sourceFilter = null)
    {
        _eventLog = new EventLog(logName);
        _isMonitoring = true;
        
        // 記錄目前最新索引,避免重複讀取舊事件
        int lastIndex = _eventLog.Entries.Count - 1;
        
        Task.Run(() => 
        {
            while (_isMonitoring)
            {
                try
                {
                    int currentCount = _eventLog.Entries.Count;
                    for (int i = lastIndex + 1; i < currentCount; i++)
                    {
                        var entry = _eventLog.Entries[i];
                        if (sourceFilter == null || entry.Source == sourceFilter)
                        {
                            OnNewEntry(entry);
                        }
                    }
                    lastIndex = currentCount - 1;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("監控錯誤: " + ex.Message);
                }
                Thread.Sleep(1000); // 每秒輪詢一次
            }
        });
    }

    public void StopMonitoring() => _isMonitoring = false;

    protected virtual void OnNewEntry(EventLogEntry entry)
    {
        Console.WriteLine($"[{entry.TimeGenerated:HH:mm:ss}] {entry.EntryType} - {entry.Source}: {entry.Message}");
    }
}

實務範例 3:寫入自訂應用程式日誌

public class ApplicationLogger
{
    private const string SourceName = "MyApp";
    private const string LogName = "Application";

    public ApplicationLogger()
    {
        // 首次執行需註冊來源 (需管理員權限)
        if (!EventLog.SourceExists(SourceName))
        {
            EventLog.CreateEventSource(SourceName, LogName);
        }
    }

    public void LogInfo(string message, int eventId = 1000)
    {
        EventLog.WriteEntry(SourceName, message, EventLogEntryType.Information, eventId);
    }

    public void LogError(string message, Exception ex = null, int eventId = 1001)
    {
        string fullMessage = ex != null ? $"{message}\n{ex}" : message;
        EventLog.WriteEntry(SourceName, fullMessage, EventLogEntryType.Error, eventId);
    }

    public void LogWarning(string message, int eventId = 1002)
    {
        EventLog.WriteEntry(SourceName, message, EventLogEntryType.Warning, eventId);
    }
}

遠端電腦日誌讀取

// 讀取遠端電腦的系統日誌 (需具備遠端電腦管理權限)
EventLog remoteLog = new EventLog("System", "192.168.1.100", "System");
// 或指定認證 (需搭配 Impersonation 或 WMI)

效能與最佳實務建議

  • 使用 Cast<EventLogEntry>() + LINQ:Entries 是非泛型集合,搭配 LINQ 篩選極為方便
  • 避免一次載入所有項目:大型日誌可能有數十萬筆,使用 Take()、Skip() 分頁讀取
  • 快取最後讀取索引:輪詢模式下記錄 Entries.Count 避免重複處理
  • 非同步處理:UI 應用請使用 Task.Run 避免阻塞主執行緒
  • 權限管理:讀取 Security 日誌需管理員權限;寫入需註冊 Source (安裝時以管理員身分執行一次)
  • 釋放資源:EventLog 實作 IDisposable,請搭配 using 區塊

常見問題排查

總結

EventLog 與 EventLogEntry 是 .NET 存取 Windows 事件日誌的標準介面。掌握其核心屬性、篩選技巧與監控模式,能幫助開發者建立系統監控工具、診斷輔助程式、安全稽核系統等實務應用。搭配 LINQ 與非同步模式,可高效處理大量日誌資料。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因解決
System.Security.SecurityException權限不足以管理員身分執行、或授予事件日誌讀取權限
System.ArgumentException: 來源不存在寫入前未註冊 Source呼叫 EventLog.CreateEventSource() 註冊 (需管理員)
遠端讀取失敗RPC/防火牆/權限開放 TCP 135/445、確認遠端登入權限、使用同網域帳號
中文訊息顯示亂碼編碼問題.NET 通常自動處理,若仍有問題請檢查系統地區設定