6.2 事件记录.htm
来自「Windows2000后台服务程序开发手册」· HTM 代码 · 共 499 行 · 第 1/3 页
HTM
499 行
.evt。正常情况下,事件检视器会抓取登录子机码,附加
.evt延伸档名,并且尝试使用此文件名称去开启一个记录档。然而,您可以撤消此行为并指定一个自订的路径名称给被加至Logname机码下之文件登录值的记录档。这个改变路径名称的方法需要重新启动系统以使改变生效。注意到之前已改变的记录资讯不会显示在新的记录中。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>有二个影响一个记录的登录值应该被提出来说明。第一个为MaxSize,它的型别为REG_DWORD。这个值是系统允许记录档之最大值,以位元组表示。第二个值是Retention,它的型别也是REG_DWORD。这个值指定在它自动地从记录档中删除前,一个事件在短时间内应该多大。您的程序代码可以自由的去修改这些值。如果MaxSize与Retention值不存在一个被给定的登录中,系统会预设最大的记录文件大小为512
KB和7天的保留时间。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您不太可能会在登录中手动地改变这些值。更确切地说,您大概会使用事件检视器嵌入式管理单元选择一个记录并显示它的内容对话方块来改变它们。图6-2显示了一个记录的内容对话方块。</FONT></P>
<P><BR style="LINE-HEIGHT: 25px"> </P>
<CENTER style="LINE-HEIGHT: 25px">
<P><INPUT id=2 style="LINE-HEIGHT: 25px" type=image height=416
width=404 src="6.2 事件记录.files/6-2.gif" border=0
onclick="imgclick"></P></CENTER>
<CENTER style="LINE-HEIGHT: 25px">
<TABLE style="LINE-HEIGHT: 25px" border=0>
<TBODY style="LINE-HEIGHT: 25px">
<TR style="LINE-HEIGHT: 25px">
<TD style="LINE-HEIGHT: 25px" align=middle><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial
color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 图6-2 </B></FONT>应用程序记录档的内容对话方块</FONT></TD></TR></TBODY></TABLE></CENTER>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>既然我们已经讨论了用您的事件来源记录事件和与其联系的讯息DLL,那么现在是将讯息文件的细节讨论与上述两个主题结合的时候。</FONT></P></A><A
style="LINE-HEIGHT: 25px" name=206003>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e70d7
size=5><B style="LINE-HEIGHT: 25px">建立讯息DLL与EXE<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>我们还必须回答的问题如下:</FONT></P><FONT style="LINE-HEIGHT: 25px"
face=arial color=#000000 size=2>
<UL style="LINE-HEIGHT: 25px">
<LI style="LINE-HEIGHT: 25px">讯息文件中的文字如何与一个事件结合?<BR
style="LINE-HEIGHT: 25px">
<LI style="LINE-HEIGHT: 25px">ReportEvent的ppszStrings参数如何获得利用?<BR
style="LINE-HEIGHT: 25px">
<LI style="LINE-HEIGHT: 25px">我们如何建立一个讯息DLL?<BR
style="LINE-HEIGHT: 25px"> </LI></UL></FONT>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>本节中将会回答上述的所有问题。图6-3显示了所有的事件记录结构,包含建立一个讯息DLL所需的步骤。您将会在后续的讨论中参考到此图。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您的第一个建立讯息DLL的步骤是为您的讯息来源建立一个文件。此讯息来源一般被称为「MC」文件,而且,可以使用任何您所选择的名称,只要它的延伸档为
.mc。例如,MyMsgs.mc。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您的 .mc文件被架构为一系列的讯息项目,并以任意的顺序安排。请参阅《Platform
SDK》文件以取得完整的讯息文件之语法。以下为一个讯息文件的范例:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">;/************************************************************** <BR>;Module name:MyMsgs.mc <BR>;**************************************************************/ <BR>;//*********************MESSAGE SECTION *********************** <BR>MessageIdTypedef=DWORD <BR>MessageId=0x1 <BR>SymbolicName=MSG_DATE <BR>Language=English <BR>Today’s date is %1. %%536871912 <BR>. <BR>MessageId=0x2 <BR>SymbolicName=MSG_TIME <BR>Language=English <BR>The current time is %1. %%536871912 <BR>. <BR>MessageId= <BR>SymbolicName=MSG_SEC <BR>Language=English <BR>The seconds are %1. %%536871912 <BR>. <BR>;//****************STRING PARAMETERS SECTION ****************** <BR>MessageIdTypedef=DWORD <BR>MessageId=0x100 <BR>Language=English <BR>I hope you enjoy today. <BR>. <BR>;//************************END OF FILE ************************</PRE></FONT></DIV>
<P><BR style="LINE-HEIGHT: 25px"> </P>
<CENTER style="LINE-HEIGHT: 25px">
<P><INPUT id=3 style="LINE-HEIGHT: 25px" type=image height=603
width=550 src="6.2 事件记录.files/6-3.gif" border=0
onclick="imgclick"></P></CENTER>
<CENTER style="LINE-HEIGHT: 25px">
<TABLE style="LINE-HEIGHT: 25px" border=0>
<TBODY style="LINE-HEIGHT: 25px">
<TR style="LINE-HEIGHT: 25px">
<TD style="LINE-HEIGHT: 25px" align=middle><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial
color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 图6-3 </B></FONT>事件记录的架构,包含建立一个讯息DLL的步骤</FONT></TD></TR></TBODY></TABLE></CENTER>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>MessageId是与文字关联的识别码。注意到您可以在讯息文件中为这个MessageId栏位省略一个明确的值。这将会导致编译器产生比之前的讯息识别码多的识别码。SymbolicName栏位参考到产生之标头文件中将被使用的已定义巨集。您可以引入被产生的标头档与您的事件回报控制码,并且使用被SymbolicName栏位定义的巨集去确认一个讯息。Language行定义了该讯息使用的语言。您可以使用此方法建立一个为单一讯息识别码鉴定拥有若干语言支援的单一的讯息资源。因为讯息可能是几行长,所以您会在一个单一时期使用一行来指示讯息的结尾。注意此处需要一个延长的期间,而且在您的
.mc文件中的最后一个项目应该在延长期后回传Return键(Carriage Return)。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当您使用ReportEvent记录一个事件时,dwEventID参数指定了事件的识别码。后来事件检视器嵌入式管理单元会使用事件识别码的值搜寻人类可阅读字串之事件讯息文件。同样地,ReportEvent的wCategory参数会与一个在类别讯息文件中识别码相同的讯息关联。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如您所见,讯息文件的语法相当的简单,但是,有些方面需要某些附加的讨论。如前所述,事件记录的主要目的之一即是语言的独立性。讯息资源允许您容易地为了多种语言所包含的讯息。为了达成目的,您只需在被要求的语言内的讯息后面加入一个额外的Language行至每一个讯息的项目即可。它也常被用来将不同的语言编译至相同的讯息DLL中。例如,您的专案可能包含了一个MsgEnglish.dll和一个MsgFrench.dll。只要为您的讯息文件将这二个DLL含入登录项目,事件检视器嵌入式管理单元就可以找到适当的语言所代表讯息。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>到目前为止,您可能会认为对于任何给定的事件识别码来说,事件检视器会报告一个不变的细节讯息。如果您认为由编译时期定义的静态字串所组成的一个事件记录机制不是非常有用,那么您是正确的。我们需要对相同的识别码但是为不同文字之回报多个事件的能力。例如,如果您的应用程序回报它无法开启一个文件,您想要使它在事件的说明文字中动态地引入被指定的文件名称。您也许会猜想事件记录的解决方法即是位于ReportEvent内的ppszString参数。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当您建立一个讯息时,该讯息可能包含了指示特定事件字串应被放置在何处的特别字元序列。例如,以下的事件字串指示了二个可置换的字串:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">"The file %1 was replaced with the file %2"</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如果您使用ReportEvent的ppszStrings传递一个包含二个字串的阵列,事件检视器嵌入式管理单元会使用「%1」取代第一个字串,「%2」则取代第二个字串。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>通常,您应该只传递与语言无关的字串值,例如数字、文件名称以及其他资源的名称。尽管您可以传递任何文字而事件检视器嵌入式管理单元会取代它,但是例如传递一个英文片语时,便会破坏事件记录的语言独立性。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>可以与扩充的字串一起使用参数代替来从参数讯息文件包含附加的细节字串。当扩充事件字串时,一个「%%」字元序列会被附加在一个指示参数代替的数字后。例如,以下的事件字串指示一个可取代的参数字串:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">"This is an example %%237"</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当扩充此字串时,事件检视器嵌入式管理单元会搜寻一个识别码为237的字串,且以参数字串取代事件字串的「%%237」之参数讯息文件的讯息表格资源参数。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>此外,参数扩充在字串扩充后才被执行,它考虑到复杂的扩充情形。假设讯息字串「Replace with a dynamic
parameter
%%%1」与一个值为「237」的字串会被传递至ReportEvent。事件检视器嵌入式管理单元会先取代「%1」,然后继续使用在参数讯息文件中有237的识别码取代「%%237」。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如果您将您的事件来源之ParameterMessageFile登录值设定至Kernel32.dll,那么您可以使用从GetLastError回传的值而动态地插入错误讯息文字。例如,假设Kernel32.dll是您的参数讯息文件,而您的讯息字串是「GetLastError()
returned the following error:
%%%1」。您可以用一个单一字串值「5」呼叫ReportEvent以指示为拒绝存取。事件讯息的结果将会是:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">"GetLastError()returned the following error:Access is denied".</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>能在您的事件说明中插入最后的错误讯息文字,确实是一个有用的特性。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e72d7
size=4><B style="LINE-HEIGHT: 25px">编译您的讯息<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在您建立 .mc文件后,您需要使用附加在Microsoft Visual Studio中的Message
Compiler(Mc.exe)来编译它。以下的文字显示编译器的使用方法:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">C:\>mc.exe <BR>Microsoft (R) Message Compiler Version 1.00.5239 <BR>Copyright (c) Microsoft Corp 1992-1995.All rights reserved. <BR>用法:MC [-?vcdwso] [-m maxmsglen] [-h dirspec] [-e extension] <BR> [-r dirspec] [-x dbgFileSpec] [-u] [-U] filename.mc <BR> -? - 显示此讯息。 <BR> -v - 产生冗长的输出。 <BR> -c - 在所有的讯息识别码中设定Customer位元。 <BR> -d - 标头档中的FACILTY与SEVERITY值,以十进制值表示。 <BR> 设定标头中的讯息值为以十进制初始。 <BR> -w - 如果讯息文字中包含非OS/2相容之插入物时,发出警告。 <BR> -s - 插入符号连结名称以视为每一个讯息的第一行。 <BR> -o - 产生OLE2标头档(使用HRESULT定义取代状态控制码定义)。 <BR> -m maxmsglen - 如果任何讯息的大小超过maxmsglen所设定之字元数时,产生一个警告。 <BR> -h pathspec - 设定建立C含入文件之路径,预设值是 .\。 <BR> -e extension - 指定档头文件之延伸名称。 <BR> 1到3个字元。 <BR> -r pathspec - 设定建立RC含入文件与含入之二进位码讯息资源文件的路径。 <BR> 预设值是 .\。 <BR> -x pathspec - 设定建立 .dbg之讯息识别码与符号名称对应的C含入文件路径。 <BR> -u - 输入文件为Unicode格式。 <BR> -U - 在 .BIN文件中的讯息应为Unicode。 <BR> filename.mc - 设定一个用于编译的讯息文字文件名称。 <BR> 产生的文件使得保存(Archive)位元被清除。</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>讯息编译器会剖析您的 .mc文件并产生叁个文件:</FONT></P><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000 size=2>
<UL style="LINE-HEIGHT: 25px">
<LI style="LINE-HEIGHT: 25px"><FONT style="LINE-HEIGHT: 25px"
face=arial color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> MSG00001.bin </B></FONT>此文件包含了所有二进位码格式的讯息字串。它也包含了对应一个讯息识别号码至字串的资讯。<BR
style="LINE-HEIGHT: 25px">
<LI style="LINE-HEIGHT: 25px"><FONT style="LINE-HEIGHT: 25px"
face=arial color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> MyMsgs.rc </B></FONT>此资源指令码文件中只有一个参考至包含在MSG00001.bin文件的二进位码讯息。<BR
style="LINE-HEIGHT: 25px">
<LI style="LINE-HEIGHT: 25px"><FONT style="LINE-HEIGHT: 25px"
face=arial color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> MyMsgs.h </B></FONT>此文件是一个C/C++
标头文件,包含了出现在
.mc文件之任何符号名称的#define。您应该在您的原始码模组中呼叫ReportEvent,以含入此文件。<BR
style="LINE-HEIGHT: 25px"> </LI></UL></FONT>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e72d7
size=4><B style="LINE-HEIGHT: 25px">资源文件<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在经由讯息编译器执行MyMsgs.mc后,我用一个非常简单的资源指令档(MyMsgs.rc)来结束它,该文件看起来像图6-4所示的内容一样:</FONT></P>
<P><BR style="LINE-HEIGHT: 25px"> </P>
<CENTER style="LINE-HEIGHT: 25px">
<P><INPUT id=4 style="LINE-HEIGHT: 25px" type=image height=335
width=500 src="6.2 事件记录.files/6-4.gif" border=0
onclick="imgclick"></P></CENTER>
<CENTER style="LINE-HEIGHT: 25px">
<TABLE style="LINE-HEIGHT: 25px" border=0>
<TBODY style="LINE-HEIGHT: 25px">
<TR style="LINE-HEIGHT: 25px">
<TD style="LINE-HEIGHT: 25px" align=middle><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial
color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 图6-4 </B></FONT>一个被讯息编译器产生的资源指令档</FONT></TD></TR></TBODY></TABLE></CENTER>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您可能已经很熟悉图示、点阵图以及对话方块范本的资源,一个讯息表格不过是资源的另一种型别而已。就像是图示与点阵图,其讯息表格资源是在资源指令中参照的二进位文件,而对话方块范本与功能表范本则嵌入在指令档中。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如果您在Platform SDK中开启WinUser.h标头文件,您将会发现以下被定义之设备符号:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">#define RT_CURSOR MAKEINTRESOURCE(1) <BR>#define RT_BITMAP MAKEINTRESOURCE(2) <BR>#define RT_ICON MAKEINTRESOURCE(3) <BR>#define RT_MENU MAKEINTRESOURCE(4) <BR>#define RT_DIALOG MAKEINTRESOURCE(5) <BR>#define RT_STRING MAKEINTRESOURCE(6) <BR>#define RT_FONTDIR MAKEINTRESOURCE(7) <BR>#define RT_FONT MAKEINTRESOURCE(8) <BR>#define RT_ACCELERATOR MAKEINTRESOURCE(9) <BR>#define RT_RCDATA MAKEINTRESOURCE(10) <BR>#define RT_MESSAGETABLE MAKEINTRESOURCE(11) // 看这里! <BR>#define RT_GROUP_CURSOR MAKEINTRESOURCE(12) <BR>#define RT_GROUP_ICON MAKEINTRESOURCE(14) <BR>#define RT_VERSION MAKEINTRESOURCE(16) <BR>#define RT_DLGINCLUDE MAKEINTRESOURCE(17) <BR>#define RT_PLUGPLAY MAKEINTRESOURCE(19) <BR>#define RT_VXD MAKEINTRESOURCE(20) <BR>#define RT_ANICURSOR MAKEINTRESOURCE(21) <BR>#define RT_ANIICON MAKEINTRESOURCE(22) <BR>#define RT_HTML MAKEINTRESOURCE(23)</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>讯息表格资源已经被指定为号码11。当您加入资源至一个资源指令码(.rc)档时,您必须为每一个资源的类型指定一个唯一的数字。例如,我可以加入一个识别码为53的图示至我的资源指令码中,然后加入另一个识别码为172的图示至我的资源指令码中。这些数字实际上并不重要,因为它们是唯一的。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>讯息表格资源与其他资源的工作有些不同。一个资源指令码文件可以只拥有一个讯息表格资源,而且该资源必须被指定识别码为1。如果您指定一个不同的识别码给讯息表格资源,在使用像事件检视器嵌入式管理单元时将无法将事件与类别识别码转换成人类可阅读的字串。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>如果您的讯息DLL或EXE包含了附加的资源,只要将被讯息编译器产生的 .rc文件内容复制至您拥有的
.rc文件中即可。然后您可以丢弃被讯息编译器产生的 .rc档。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e72d7
size=4><B style="LINE-HEIGHT: 25px">使用Visual Studio建立一个讯息文件之专案<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>虽然您可以在每一次改变您的讯息时,手动地执行讯息编译器工具,然而那么做会变得麻烦且乏味。我强烈地建议为您的DLL或EXE加入讯息编译的步骤至您的Visual
Studio专案中。由于一些未知的原因,Visual Studio环境无法察觉到这个讯息编译器与
.mc文件,所以您需要在专案中加入自订的建立步骤。步骤如下:</FONT></P><FONT
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?