建立新工程时,我喜欢尽快看到运行结果,所以我决定服务程序要做的第一件事情是建立一个系统应用程序日志记录。借助这个日志记录机制,我能跟踪服务何时启动, 何时停止等等。我还可以记录服务中发生的任何出错信息。创建这个日志记录比我想象的要复杂得多。 逆风编程精品
建立日志记录
我想,既然日志文件是操作系统的一部分,那么肯定有应用程序编程接口(API)来支持建立日志记录。所以我开始搜索 MSDN CD,直到发现 ReportEvent 函数为止。如果你不熟悉这个函数,你可能会想,这个函数应该知道在哪个日志文件建立记录,以及你想要插入的文本信息。没错,这都是它要做的事情,但是为了简化出错信息的国际化,该函数有一个消息 ID 作为参数,并在你提供的消息表中查找消息。所以问题无非是你想将什么消息放入日志,以及如何将这些消息添加到你的应用程序中,下面我们一步一步来做:
- 以 .MC 为扩展名创建一个包含消息描述的文本文件。我将它命名为 NTServMsg.mc。该文件的格式非常特别,具体细节参见 Platform SDK 文档;
- 针对你的源文件运行消息编译器(mc.exe),默认情况下它创建名为 MSG00001.BIN 的输出文件。编译器还创建一个头文件(在我的例子程序中,该头文件是 NTServMsg.h)和一个.RC 文件(NTServMsg.rc)。只要你修改工程的 .MC 文件就必须重复这一步,所以把工具加到 Visual C 的工具菜单里做起来会很方便;
- 为工程创建一个 .RC 文件,将 WINDOWS.H 头文件以及消息编译器产生的 .RC 文件包含到其中;
- 在主工程头文件中包含消息编译器产生的头文件,以便模块可以存取符号消息名;
下面让我们仔细一下这些文件,以便弄明白你自己需要创建什么,以及消息编译器要为你创建些什么。我们不用研究整个消息集,只要看看其中一二个如何工作的即可。下面是例子程序消息源文件 NTServMsg.mc 的第一部分:
MessageId=100
SymbolicName=EVMSG_INSTALLED
Language=English
The %1 service was installed.
.
MessageId=
SymbolicName=EVMSG_REMOVED
Language=English
The %1 service was removed.
.
MessageId=
SymbolicName=EVMSG_NOTREMOVED
Language=English
The %1 service could not be removed.
.
每一条都有一个消息ID,如果不特别设置,那么 ID 的取值就是指其前面所赋的值。每一条还有一个代码中使用的符号名,语言标示符以及消息文本。消息可以跨多个行,并用含有一个句号的单独一行终止。
消息编译器输出一个库文件,该库文件被用作应用程序的资源,此外还输出两个要在代码中包含的文件。下面是我的 .RC 文件:
// NTServApp.rc
#include <windows.h>
// 包含由消息编译器(MC)产生的消息表资源脚本
#include "NTServMsg.rc"
Here''s the .RC file the message compiler generated:
LANGUAGE 0x9,0x1
1 11 MSG00001.bin
正像你所看到的,这些文件中内容不多!
消息编译器产生的最后一个文件是你要包含到代码中的头文件,下面就是这个头文件的部分内容:
[..........]
//
// MessageId: EVMSG_INSTALLED
//
// MessageText:
//
// The %1 service was installed.
//
#define EVMSG_INSTALLED 0x00000064L
//
// MessageId: EVMSG_REMOVED
//
// MessageText:
//
// The %1 service was removed.
//
#define EVMSG_REMOVED 0x00000065L
[...........]
你可能已经注意到了有几个消息包含参数替代项(如 %1)。让我们看看将消息写入某个系统日志文件时如何在代码中使用消息ID和参数替代项。以事件日志中记录成功安装信息的部分安装代码为例。也就是 CNTService::IsInstalled 函数部分:
本文章更多内容:<<上一页 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 下一页>> |