1、 目的
應用系統的開發和維護離不開日志系統,選擇一個功能強大的日志系統解決方案是應用系統開發過程中很重要的一部分。在.net環境下的日志系統解決方案有許多種,log4net是其中的佼佼者。
在Windows2000及以上操作系統中,有一個Windows日志系統,它包括應用程序(Application)事件日志、系統(System)日志和安全(Security)日志,事件日志也可以是自定義日志。在.net Framework中也提供了相應的類和接口來使用應用程序事件日志或者自定義事件日志。使用Windows日志可以使應用系統與操作系統更好的結合,與單純使用自定義的日志系統相比,因為有了操作系統的支持,查詢和管理日志更方便。在實際應用中,根據實際情況,可以選擇一種合適的日志解決方案,也可以自定義日志系統和Windows日志系統兩種日志解決方案同時使用。
2、 使用Windows日志的方法
2.1、方法概述
在.net Framework中提供了一個類EventLog,使用EventLog類可以添加新的事件日志條目或從服務器事件日志中獲取已有的條目。EventLog類包括一個WriteEntry()方法,可以用它來把一個新的事件寫入到事件日志中。在寫入一個新的條目到事件日志時,是使用特定的事件源(event source)來把條目寫入到特定的事件日志中。
事件源對於事件日志而言是唯一的。在Windows2000及以上操作系統中,包括一個事件日志:應用程序(Application)事件日志,還有系統(System)日志和安全(Security)日志,並且系統允許自定義事件日志。使用EventLog類,可以將日志條目添加到應用程序(Application)事件日志中,也可以添加到自定義事件日志中。事件源相當於事件日志的下一級目錄,每一條日志條目都必須對應一個事件源。EventLog類可以創建一個自定義事件日志,也可以創建一個事件源,事件源可以創建在應用程序(Application)事件日志中,也可以創建在自定義事件日志中。Windows日志系統如下圖所示:
為了便於不同應用系統之間的日志區分和查看方便,一般將事件源創建在自定義事件日志中,可以創建多個事件日志,一個事件日志也可以創建多個事件源。
2.2、事件日志和事件源創建方法
創建一個新的事件日志或事件源時,其實是在對注冊表添加一個條目。由於寫注冊表要求特殊的權限,所以在Web項目中創建事件日志和事件源就存在權限和安全的問題,Application項目中不存在此問題,本文重點講述Web項目中Windows日志使用方法,Application項目中的使用方法類似於Web項目,拋棄掉Web項目中的權限和安全處理即可,本文不再贅述。
在Web項目中,當使用asp.net向系統中創建一個事件日志或者一個事件源時,可能會得到如下異常錯誤消息: System.Security.SecurityException: 不允許所請求的注冊表訪問權。這是因為運行asp.net進程的默認帳戶是ASPNET(在IIS6.0下面是NetworkService),而此賬戶默認只有讀權限,沒有寫權限,所以不能創建事件日志或事件源。解決此問題的辦法有提升ASPNET帳戶的權限、不在程序內部創建事件日志或事件源等,主要有以下三種解決方案:
A、 在程序運行之前,定義要使用的事件日志和事件源,打開注冊表編輯器,手工將事件日志和事件源添加到注冊表中。主要步驟如下:
① 點擊“開始”菜單,再點擊“運行”。
② 在“運行”的“打開”框中輸入“regedit”,然後按OK按鈕,打開注冊表編輯器。
③ 在注冊表編輯器中找到下列子鍵:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog
④ 右鍵單擊“Eventlog”,點擊“新建”,再點“項”,將在“Eventlog”的下一級創建一個新的項目,將此項目命名為“TDDN”, TDDN項就是事件日志,可以根據實際情況為此項命名,比如可以命名為項目名稱。
⑤ 在“TDDN”項上單擊右鍵,點擊“新建”,再點“項”,將在“TDDN”的下一級創建一個新的項,將此項命名為“Weblog”, Weblog項就是事件源,此項也可以根據實際情況命名。
⑥ 關閉注冊表編輯器。
這樣事件日志和事件源就建好了,如果需要多個事件日志或事件源,重復以上過程。這種方法要求對注冊表比較熟悉,操作起來可能有一點復雜,可以寫一個類來實現配置注冊表,只要運行該類便可添加相應的項目,免除了手工添加的繁瑣,這是第二種解決方案,方法如下:
B、 在System.Diagnostics命名空間中有一個EventLogInstaller類,它能夠創建和配置應用程序在運行時要讀寫的事件日志和事件源。通過下列步驟,便能夠使用EventLogInstaller類來創建一個事件日志和事件源:
① 用C#來創建一個名為EventLogSourceInstaller的“類庫”。
② 在此項目中添加對System.Configuration.Install.dll的引用。
③ 將自動產生的Class1.cs更名為MyEventLogInstaller.cs。
④ 在MyEventLogInstaller.cs中的寫入以下代碼:
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Configuration.Install;
namespace EventLogSourceInstaller {
[RunInstaller(true)]
public class MyEventLogInstaller: Installer{
public EventLogInstaller myEventLogInstaller;
public MyEventLogInstaller(){
//Create Instance of EventLogInstaller
myEventLogInstaller = new EventLogInstaller();
// Set the Source of Event Log, to be created.
myEventLogInstaller.Source = "WebLog";
// Set the Log that source is created in
myEventLogInstaller.Log = "TDDN";
Installers.Add(myEventLogInstaller);
}
}
}
⑤ 生成此項目,得到EventLogSourceInstaller.dll。
⑥ 打開Visual Studio .NET 命令提示,轉到EventLogSourceInstaller.dll所在目錄。
⑦ 運行此命令來創建事件日志和事件源,運行方法為:輸入命令InstallUtil EventLogSourceInstaller.dll。
這樣程序就在系統中創建一個事件日志:TDDN,在事件日志TDDN下創建了一個事件源:WebLog。
以上的這兩種解決方案都是在應用系統運行之前,為系統手工添加事件日志和事件源,這樣做沒有安全權限問題,不存在安全隱患。更方便的方法還可以在應用系統運行時,讓程序自動創建事件日志和事件源,這種方法必須提升ASPNET帳戶的系統操作權限,或者給asp.net進程一個有更大權限的模擬帳號。模擬帳號的實現比較復雜,而且功能和安全性上和提升ASPNET帳戶沒有區別,這裡采用的方法是提升ASPNET帳戶的權限。以下是第三種解決方案:
C、 提升ASPNET帳戶的權限可以直接在Windows系統管理中給ASPNET帳戶添加對系統的讀寫權限,但是這樣做存在很嚴重的安全問題,asp.net進程有直接讀寫操作系統的權限,將給系統帶來很大的安全隱患。這裡采用的提升ASPNET帳戶權限的方法是只將系統日志的操作權限賦給ASPNET帳戶,這樣雖然還存在一定的安全隱患,但是隱患已經大大降低,並且可以在程序內部自由創建事件日志和事件源,極大的提高了靈活性。ASPNET帳戶權限提升方法如下:
① 點擊“開始”,“運行”,輸入“regedit”,打開注冊表編輯器。
② 在注冊表編輯器中找到下列子鍵:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog
③ 在Eventlog項目上單擊右鍵,在彈出的菜單中選擇“訪問許可”選項,然後找到本機的ASPNET帳戶加進來,並賦予讀寫權限。
這樣,ASPNET帳戶就有了讀寫系統日志的權限,就可以在程序中根據情況自由創建事件日志和事件源了。在程序中創建事件日志和事件源的方法如下:
調用 EventLog類的CreateEventSource 方法並指定數據源字符串和要創建的事件日志名稱,如果將事件日志名稱指定為空 (""),事件日志名稱將默認為Application,這樣不會創建新事件日志,但會為應用程序(Application)事件日志創建指定的數據源。如果創建一個新的事件日志,則在確定事件日志名稱是否唯一時將只計算指定字符串的前8 個字母。如下代碼所示:
System.Diagnostics.EventLog.CreateEventSource("WebLog", "TDDN");
將創建一個事件日志為TDDN,在該事件日志下創建一個事件源WebLog。要在遠程計算機上創建自定義事件日志,要將此計算機名指定為第三個參數。以下代碼提供了一個示例:
System.Diagnostics.EventLog.CreateEventSource(" WebLog ", " TDDN ", "myserver");
將在遠程計算機myserver上創建該事件日志和事件源。
2.3、寫入Windows日志的方法
事件日志與事件源創建的問題解決了,接下來就可以在程序中將日志信息寫入到Windows系統日志中了。寫入方法是,首先創建EventLog類的一個實例,將其Source屬性與事件源名稱相關聯,最後調用WriteEntry方法來往事件日志中添加日志信息。下面是一段寫入系統日志的簡單示例代碼:
EventLog eventLog = null;
if (!(EventLog.SourceExists("WebLog"))){
EventLog.CreateEventSource("WebLog", "TDDN");
}
if (eventLog == null){
eventLog = new EventLog("TDDN");
eventLog.Source = "WebLog";
}
eventLog.WriteEntry("This is error!", EventLogEntryType.Error);
}
上面程序段中首先判斷數據源“WebLog”是否存在,如果不存在調用CreateEventSource方法創建該事件源,然後將事件源與EventLog 類的Source屬性關聯,進行寫操作。傳遞給WriteEntry方法的第一個參數代表要記錄的日志消息,可以寫入任何消息。第二個參數代表事件日志的類型。
A、 事件日志類型分類
事件日志的類型用於指示事件日志的嚴重度。每個事件必須具有單一的類型,應用程序在報告事件時將指示該類型。事件查看器使用該類型來確定在日志的列表視圖中顯示哪一個圖標。它分為如下五類:
① Error:錯誤事件,它指示用戶應該知道的嚴重問題(通常是功能或數據的丟失)。
② FailureAudit:失敗審核事件,它指示當審核訪問嘗試失敗(例如打開文件的嘗試失敗)時發生的安全事件。
③ Information:信息事件,它指示重要、成功的操作。
④ SuccessAudit:成功審核事件,它指示當審核訪問嘗試成功(例如成功登錄)時發生的安全事件。
⑤ Warning:警告事件,它指示並不立即具有重要性的問題,但此問題可能表示將來會導致問題的條件。
在實際應用中,選擇合適的事件日志類型,可以使日志記錄更清晰明了,幫助開發維護人員對應用系統更好的監控和維護。
B、 針對事件日志的五種類型分類,可以在應用程序中寫一個通用的類,為每一個類型寫一個方法來寫入事件日志。
下面是自定義的通用類的代碼片斷:
public void Error(string sourceName, string message){
EventLog eventLog = null;
if (!(EventLog.SourceExists(sourceName))){
EventLog.CreateEventSource(sourceName, "TDDN");
}
if (eventLog == null){
eventLog = new EventLog("TDDN");
eventLog.Source = sourceName;
}
eventLog.WriteEntry(message, EventLogEntryType.Error);
}
public void Warning(string sourceName, string message){
EventLog eventLog = null;
if (!(EventLog.SourceExists(sourceName))){
EventLog.CreateEventSource(sourceName, "TDDN");
}
if (eventLog == null){
eventLog = new EventLog("TDDN");
eventLog.Source = sourceName;
}
eventLog.WriteEntry(message,System.Diagnostics.EventLogEntryType.Warning);
}
類似的可以寫出其它三種類型的事件日志寫入方法。該類方法將事件源(sourceName)和日志消息(message)作為參數傳遞,這樣可以提高事件日志寫入的靈活性。
C、 調用通用類事件日志寫入的方法
通用類方法的調用非常簡單,如下代碼片斷是調用通用類中Error方法的一個范例:
string strSourceName="WebLog";
CoustomEventLog log=new CoustomEventLog();
log.Error(strSourceName,"This is Error!");
strSourceName是事件源,log是CoustomEventLog類(即通用類)的一個實例,然後調用Error方法將日志消息“This is Error!”寫入到事件日志中。
也可以將程序中拋出的異常信息寫入事件日志:
string strSourceName="WebLog";
CoustomEventLog log=new CoustomEventLog();
try{
//執行事件