就Windows開發(fā)者及系統(tǒng)管理員來說,Windows Vista日志相比以前,無疑有了一個(gè)很大的提高。對(duì)開發(fā)者來說,Vista的日志記錄對(duì)多種事件與日志選項(xiàng),都表現(xiàn)出統(tǒng)一一致性;而對(duì)網(wǎng)絡(luò)管理員及IT專家,它提供了豐富的人機(jī)界面用于管理事件。新的日志記錄方式,也只能通過Windows SDK中新的本機(jī)函數(shù)來實(shí)現(xiàn),下面就來看看怎樣在程序中實(shí)現(xiàn)新的記錄方式。
創(chuàng)建并編譯清單文件
如果程序中使用了新的API,且要把事件記錄到日志中,就需要?jiǎng)?chuàng)建一個(gè)清單文件(這里補(bǔ)充一點(diǎn),如果未使用新的API,或僅是使用托管程序,日志記錄還是繼續(xù)使用原來的ReportEvent* API)。清單文件是程序中所有事件基于XML格式的表現(xiàn)形式,我們可使用命令行的消息編譯器(MC.exe),利用清單文件來生成一個(gè)頭文件(*.h)及一個(gè)資源文件(*.rc)——僅限于用在C++工程中。(有關(guān)事件日志清單文件的詳細(xì)說明,請(qǐng)查閱MSDN聯(lián)機(jī)文檔,在本文中只提及了其中的一小部分。) 在清單文件中,最重要的元素就是指明了哪個(gè)“通道”(channel)可以被寫入,“通道”是Vista事件日志中一個(gè)新的概念,它根據(jù)接收者及卷,為事件提供了單獨(dú)的輸出。示例程序中使用了兩個(gè)通道:操作性(Operational)通道及調(diào)試(Debug)通道,以下的XML指定了程序?qū)⑹褂眠@兩種通道來引發(fā)事件:
在定義好通道之后,下一步就是定義一個(gè)模板以指定要引發(fā)事件的基本形態(tài)。與原來的事件日志API類似,Vista事件日志也支持使用%1這樣的通配符,以便可替換為本地化語言的文本,這樣,消息文本的所有內(nèi)容都可在運(yùn)行時(shí)才提供:
%1
最后,還需要把應(yīng)用程序?qū)嶋H將引發(fā)的事件添加到清單文件中,為簡單起見,對(duì)每個(gè)通道只定義了一個(gè)事件,且都使用同一個(gè)模板:
現(xiàn)在,消息編譯器(mc.exe)就可以把這個(gè)清單文件編譯為頭文件及資源文件了。
引發(fā)事件
實(shí)際上,在程序中引發(fā)事件是相當(dāng)?shù)睾唵危ㄖ辽倥c定義清單文件相比是這樣的),正如前面所提到的,消息編譯器生成了包含有事件及事件發(fā)布者定義的頭文件,這些信息都可傳遞給SDK函數(shù),對(duì)上面的清單文件而言,頭文件將會(huì)包含以下定義:
EXTERN_C __declspec(selectany) const GUID DOTNETPERFORMANCE_TECHNICALWRITING_PUBLISHER = { 0x9cde86c9, 0xdfb9, 0x463f, {0xb2, 0xc5,0x71,0xee,0xc2,0x32, 0xa6,0x9c}}; #define DOTNETPERFORMANCEOP 0x10 #define DOTNETPERFORMANCEDEBUG 0x0 EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR OP_EVENT = { 0x1, 0x0, 0x10, 0x4, 0x0, 0x0, 0x8000000000000000}; #define DNP_OP_EVENT_value 0x1 EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR DEBUG_EVENT = {0x2, 0x0, 0x0, 0x4, 0x0, 0x0, 0x4000000000000000}; #define DNP_DEBUG_EVENT_value 0x2 #define MSG_SimpleMessage 0xB0000001L
接下來,要在代碼中包含以下頭文件:windows.h(如果為控制臺(tái)程序)、evntprov.h(其包含了所有的Windows事件跟蹤)、winevt.h(其包含了所有新的Vista日志聲明);另外,可通過調(diào)用EventRegister來注冊(cè)事件發(fā)布者:
REGHANDLE hPub = NULL; EventRegister( &DOTNETPERFORMANCE_TECHNICALWRITING_PUBLISHER, NULL, NULL, &hPub); 實(shí)際上,引發(fā)一個(gè)事件非常之簡單:創(chuàng)建一個(gè)事件描述符并把它傳遞給EventWrite函數(shù)就可以了:
EVENT_DATA_DESCRIPTOR opEventDesc; PWSTR pwsOp = L"My Operational Event"; EventDataDescCreate(&opEventDesc, pwsOp, ((ULONG)wcslen(pwsOp)+1)*sizeof(WCHAR)); EventWrite(hPub, &DNP_OP_EVENT, 1, &opEventDesc);
代碼中的宏EventDataDescCreate定義在頭文件evntprov.h中,它只是提供了一種更短的語法用于設(shè)置變量EVENT_DATA_DESCRIPTOR的成員。
如果不再需要為特定發(fā)布者寫入事件,可取消注冊(cè): EventUnregister(hPub)
部署及使用
在部署程序之前,還需要使用以下命令來注冊(cè)清單文件:
wevtutil install-manifest 清單文件名.xml
Windows Vista自帶的wevtutil工具,將會(huì)解析清單文件并添加所需的設(shè)置到Vista日志記錄中;如果未運(yùn)行wevtutil,事件仍可被成功引發(fā),但在事件日志中將不可見。
|