0
点赞
收藏
分享

微信扫一扫

向自己的模块添加错误代码_使用vc自带的工具MC创建资源并将其添加至DLL或EXE中


本文主要介绍怎么使用Visual Studio自带的MC.exe工具来创建一个消息资源并将其添加到自己的DLL(或.exe)中,从而达到为自己的模块添加错误代码的目的。

 

一、MC工具介绍

Message Compiler(MC) 是用来创建消息资源的工具,这些消息资源被DLL(或EXE)模块引用。MC的输入是一个特定格式的文本文件,即*.mc文件,这种特定格式使得在一个文件中定义多种语言支持变得非常容易。

当编写完成一个*.mc文件之后,为了在程序中使用这个文件,你需要一些操作。首先,使用MC工具将这种文件编译成一个*.rc文件(还会生成*.h和*.bin文件);然后将*.rc及*.h添加进相应的DLL(EXE)模块中编译;最后通过相应的事件日志函数或者FomatMessage函数对其中的消息文本进行使用。(具体的操作过程请看后面的例子)

 

二、消息文本文件定义(*.mc文件)

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。

 

三、*.mc文件定义的例子

 

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进行编译,如下:

 

向自己的模块添加错误代码_使用vc自带的工具MC创建资源并将其添加至DLL或EXE中_自定义

 

编译成功后,会在当前目录下生成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;
}



五、相应例子visual studio 2005工程文件代码下载

​​工程文件下载:使用MC工具创建自定义错误代码DLL​​

 


举报

相关推荐

0 条评论