最近在開發一些 Windows Service 程式,由於過程中修修改改的,所以藉此整理一下思緒,也順手開發出一套簡易的 EventLog 管理工具,可方便建立、刪除、查詢 EventSource 的相關資訊,也可以刪除 LogName 等資料,避免程式在寫入 EventLog 的時候發生錯誤。
我想如何使用 EventLog.WriteEntry 應該不用多說了,但在使用 EventLog.WriteEntry 之前,卻有幾個蠻重要的觀念要傳達。
如果你要在 EventLog 中建立自己的 LogName 或 EventSource 必須要知道你的程式在執行時「權限」夠不夠的問題。一般來說,我們會用 EventLog.CreateEventSource 幫我們建立自訂的 EventSource 與 LogName,但是你若是以 LocalSystem 帳戶執行 Windows Service 的話,並沒有執行這個方法所需的權限,所以解決之道必須在安裝的過程中進行建立,否則在執行 EventLog.WriteEntry 時會失敗。
如果你之前已經建立了 EventSource 且也已經指派了 LogName 的話,如果因為程式修正 LogName 的名稱,且原本機器上的 EventSource 沒有刪除時,也會引發例外事件,解決之道就是先刪除舊的 EventSource 再重建時指派新的 LogName 即可。
以下程式範例我是放在 Installer 的 AfterInstall 事件中:
// 由於權限的關係,EventSource 必須要在安裝時建立
if (!EventLog.SourceExists(Program.EventSource))
{
EventLog.CreateEventSource(m_EventSource, m_EventLog);
}
// 如果安裝時發現 EventSource 的 LogName 與我們預期的名稱不同時就重建!
if (EventLog.LogNameFromSourceName(m_EventSource, ".") != m_EventLog)
{
EventLog.DeleteEventSource(m_EventSource);
EventLog.CreateEventSource(m_EventSource, m_EventLog);
}
當 Windows Service 要移除時,最好是將安裝時建立的 EventSource 一併移除。移除 EventSource 並不會連帶將 EventLog 中的資料也刪除,只是若有程式也要存取該 EventSource 時會發生例外事件。
以下程式範例我是放在 Installer 的 AfterUninstall 事件中:
if (EventLog.SourceExists(m_EventSource))
{
EventLog.DeleteEventSource(m_EventSource);
}
由於我最近都在改別人寫的 Windows Service 程式,也修改了原本的 EventSource 與 LogName 名稱,不過卻發現之前的程式所建立的 EventSource 沒有刪除,導致我改過的程式會一直 hang 住,而且好像也沒有一個方便的工具可以刪除這些沒用的 EventSource,因此我寫了一個小工具幫我做這些事,圖示如下:
原始碼與執行檔我都已經放上 CodePlex,有需要的人可以去抓來用:EventLog Manager
相關連結