标签:
本文主要介绍怎么使用Visual Studio自带的MC.exe工具来创建一个消息资源并将其添加到自己的DLL(或.exe)中,从而达到为自己的模块添加错误代码的目的。
Message Compiler(MC) 是用来创建消息资源的工具,这些消息资源被DLL(或EXE)模块引用。MC的输入是一个特定格式的文本文件,即*.mc文件,这种特定格式使得在一个文件中定义多种语言支持变得非常容易。
当编写完成一个*.mc文件之后,为了在程序中使用这个文件,你需要一些操作。首先,使用MC工具将这种文件编译成一个*.rc文件(还会生成*.h和*.bin文件);然后将*.rc及*.h添加进相应的DLL(EXE)模块中编译;最后通过相应的事件日志函数或者FomatMessage函数对其中的消息文本进行使用。(具体的操作过程请看后面的例子)
1、概述
Messages定义在一个*.mc文件中,MC工具会自动为每条消息赋一个编号,然后会生成一个*.h文件,以供程序引用其中的消息ID。
*.mc文件里定义消息最常见的语法为KEYWORD=VALUE,等号两边的空格会被忽略。下一条类似的定义以空格或者换行来分隔。其中VALUE可以是一个整型常量,或者一个类似宏标识的符号,或者是一个8个字符(或更少)的名字。
2、注释
单行注释:以一个分号开头,然后后面接注释文字,为了在生成的*.h文件中也以注释状态出现,勿必在分号后面撞上一个//。如下:
;//这是一个单行注释
多行注释:每行都以分号开头,但是为了同样的目的,勿必如以下写多行注释:
;/*这是多行注释
;这是多行注释
;这是多行注释*/
3、头部定义块
*.mc文件以头部定义开始,头部定义一些名字标识以及语言标识供后面消息定义使用。头部通常包含以下0个或多个声明(可以是多个相同的声明,比如语言部分)。
MessageIdTypedef=type----用于消息标识定义的类型,如#define name ((type)0xnnnnnnnn) 注:在*.h文件中可看到此类定义。这个类型必须能够容下消息码的范围(32位),比如DWORD。这个类型也可以是程序部分中自定义的。默认状态下是无类型的,也就没有相应的转换。你可以在需要使用这个声明时,才开始定义它。如:MessageIdTypedef=DWORD。
SeverityNames=(name=number[:name])----设置消息码中第31、30位,即Severity部分。
默认的设置如下:
SeverityNames=(
Success=0x0
Informational=0x1
Warning=0x2
Error=0x3
)
FacilityNames=(name=number[:name])----设置消息码中27--16位,即Facility部分,默认的设置如下:
FacilityName=(
System=0x0FF
Application=0xFFF
)
LanguageNames=(name=number:filename)----设置消息所用语言标识,可设置多个语言版本。默认的设置如下:
LanguageNames=(English=1:MSG0001),其中1可由宏MAKELANGID生成,比如生成简体中文的,MAKELANGID( LAN_CHINES, SUBLANG_CHINESE_SIMPLIFIED),生成的值 为0x804,则我们可以定义LanguageNames=(Chinese=0x804:MSG0804),其中MSG0804是我们自定义的名字,生成的*.bin文件会以其命令,如MSG0804.bin。
OutputBase=number----生成消息常量数值格式,比如指定16,生成16进制的数,指定10,生成10进制的数等。
4、消息主体定义
消息文本文件包含以下0个或多个声明,其中MessageId标识了一个消息定义的开始,必须存在,Severity、Facility声明是可选的。
MessageId=[number|+number]----消息序号标识,这项必须要有,但是值是可选的。如果没有指定值,此值等于上一个Facility加上1,如果在指定的值前面带上了一个+号,则用上一个Facility加上此值来生成MessageId。
Severity=name----在头部声明FacilityNames指定的一个名字,这个声明是可选的。如果没有指定值,则使用在消息定义块中最后指定的那个值。默认的第一个消息定义是
Facility=Application。
SymbolicName=name----一个标识符,在*.h文件中可看到,如#define name ((type)0xnnnnnnnn)。
OutpubBase={number}----生成消息常量数值格式,比如指定16,生成16进制的数,指定10,生成10进制的数等。
Language=name----在头部声明LanguageNames指定的一个名字,此项是可选项,如果没有指定值,则使用在消息定义块中最后指定的那个值。默认的第一个消息定义是
Language=English。
Message Text----消息文本。
.(点号) ----消息定义终止符,注:此终止符为英文输入模式下输入,否则使用mc工具进行编译时会提示无终止符的。消息定义例子如下:
MessageId=0x1
Severity=Error
Facility=Runtime
SymbolicName=MSG_BAD_COMMAND
Language=English
You have chosen an incorrect command.
.
Language=Chinese
你选择了一个不正常的命令。
.
你还可以在消息文本定义中使用一些控制符,具体的可查看MSDN。
1、文件内容,文件名字McFile.mc
;//***** Sample.mc ***** ;//This is the header section. MessageIdTypedef=DWORD SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS Informational=0x1:STATUS_SEVERITY_INFORMATIONAL Warning=0x2:STATUS_SEVERITY_WARNING Error=0x3:STATUS_SEVERITY_ERROR ) FacilityNames=(System=0x0:FACILITY_SYSTEM Runtime=0x2:FACILITY_RUNTIME Stubs=0x3:FACILITY_STUBS Io=0x4:FACILITY_IO_ERROR_CODE ) LanguageNames=(English=0x409:MSG00409) LanguageNames=(Chinese=0x804:MSG00804) ; // The following are message definitions. MessageId=0x1 Severity=Error Facility=Runtime SymbolicName=MSG_BAD_COMMAND Language=English You have chosen an incorrect command. . Language=Chinese 你选择了一个不正常的命令。 . MessageId=0x2 Severity=Warning Facility=Io SymbolicName=MSG_BAD_PARM1 Language=English Cannot reconnect to the server. . Language=Chinese 无法连接服务器。 . MessageId=0x3 Severity=Success Facility=System SymbolicName=MSG_STRIKE_ANY_KEY Language=English Press any key to continue . . . %0 . Language=Chinese 按任意键继续... . MessageId=0x4 Severity=Error Facility=System SymbolicName=MSG_CMD_DELETE Language=English File %1 contains %2 which is in error . Language=Chinese 文件 %1 包含 %2 r损坏。 . MessageId=0x5 Severity=Informational Facility=System SymbolicName=MSG_RETRYS Language=English There have been %1!d! attempts with %2!d!%% success%! Disconnect from the server and try again later. . Language=Chinese 未知错误!无法连接服务器,请稍后重试! .
2、使用MC工具编译
打开visual studio的命令行界面,进入McFile.mc文件目录,使用命令mc -a -A McFile.mc进行编译,如下:
编译成功后,会在当前目录下生成McFile.h,McFile.rc,MSG00409.bin,MSG00804.bin四个文件,因为文本文件中支持中英文,所以生成了两个*.bin文件。
McFile.h文件部分预览如下:
//***** Sample.mc ***** //This is the header section. // The following are message definitions. // // Values are 32 bit values layed out as follows: // // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +---+-+-+-----------------------+-------------------------------+ // |Sev|C|R| Facility | Code | // +---+-+-+-----------------------+-------------------------------+ // // where // // Sev - is the severity code // // 00 - Success // 01 - Informational // 10 - Warning // 11 - Error // // C - is the Customer code flag // // R - is a reserved bit // // Facility - is the facility code // // Code - is the facility's status code // // // Define the facility codes // #define FACILITY_SYSTEM 0x0 #define FACILITY_STUBS 0x3 #define FACILITY_RUNTIME 0x2 #define FACILITY_IO_ERROR_CODE 0x4 // // Define the severity codes // #define STATUS_SEVERITY_WARNING 0x2 #define STATUS_SEVERITY_SUCCESS 0x0 #define STATUS_SEVERITY_INFORMATIONAL 0x1 #define STATUS_SEVERITY_ERROR 0x3 // // MessageId: MSG_BAD_COMMAND // // MessageText: // // You have chosen an incorrect command. // #define MSG_BAD_COMMAND ((DWORD)0xC0020001L)
3、将生成的资源文件编译进dll(或exe)模块中。
创建一个WIN32DLL工程,将McFile.h与McFile.rc文件添加进去,进行编译,生成相应的dll即可提供给我们的程序使用。
#include <iostream> #include <windows.h> using namespace std; // #ifdef _UNICODE #define COUT wcout #else #define COUT cout #endif int main() { DWORD dwError = 0; DWORD dwLanguageId = MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ); //解决问题:wcout输出时显示不了中文 COUT.imbue( std::locale( "chs" ) ); HLOCAL lpMsgTextBuf = NULL; COUT << TEXT("输入一个自定义的错误代码(如:3221356545(0xC0020001) ):"); while( cin >> dwError ) { lpMsgTextBuf = NULL; HMODULE ghResDll = LoadLibrary( TEXT("WinMsgDll.dll") ); if ( NULL == ghResDll ) { COUT << TEXT("加载消息模块失败!") << endl; return -1; } BOOL bOk = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, ghResDll, dwError, dwLanguageId, (LPTSTR)&lpMsgTextBuf, 0, NULL ); if ( !bOk ) { COUT << TEXT("error ") << GetLastError() << endl; } if ( NULL != lpMsgTextBuf ) { COUT << (LPTSTR)lpMsgTextBuf << endl; LocalFree( lpMsgTextBuf ); } COUT << TEXT("输入一个自定义的错误代码(如:3221356545(0xC0020001) ):"); } return 0; }
作者:山丘儿
转载请标明出处,谢谢。原文地址:http://blog.csdn.net/s634772208/article/details/46402677
向自己的模块添加错误代码_使用vc自带的工具MC创建资源并将其添加至DLL或EXE中
标签:
原文地址:http://blog.csdn.net/s634772208/article/details/46402677