向自己的模块添加错误代码_使用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进行编译,如下:

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

作者:山丘儿

转载请标明出处,谢谢。原文地址:http://blog.csdn.net/s634772208/article/details/46402677

时间: 2024-08-05 11:16:09

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

用ideal创建java项目,并添加maven管理

第一步 创建项目 File->New->Project 第二步 修改项目结构 在项目的src下面创建main/java和main/resources目录. File->Project Structure 或者快捷键Ctrl+Shift+Alt+s.将Sources定位到java目录下,将Resources定位到resources下面. 此处补充idea下的java项目关于不同资源的标识符. Sources 一般用于标注类似 src 这种可编译目录.有时候我们不单单项目的 src 目录要可

Java-单机版的书店管理系统(练习设计模块和思想_系列 四(2) )

说明: 本博客为补全上篇-Java-单机版的书店管理系统(练习设计模块和思想_系列 四(1) )的,所以如果不懂,请先看上一篇. 本系列都是我一步一步学习来的, 所以,可能比较适合初学设计模块的人来学. 现在补全我目前写的所以代码: 公共类: 用户类型枚举:UserTypeEnum类 package cn.hncu.bookStore.common; /** * 功能:用户类型的枚举!<br/> * 定义在公共模块.<br/> * 变量:<br/> * ADMIN(1,

js 如何动态添加数组_百度知道

1.数组的创建var arrayObj = new Array(); //创建一个数组var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度var arrayObj = new Array([element0[, element1[, ...[, elementN]]]]); 创建一个数组并赋值 要说明的是,虽然第二种方法创建数组指定了长度,但实际上所有情况下数组都是变长的,也就是说即使指定了长度为5,仍然可以将元素存储在规定长度以外

Sql语句在SqlServer中创建数据库、表格并添加约束

通过Sql语句来创建数据库与架构 创建数据库 数据库的创建首先是要引用主数据库的,需要在master数据库的环境下进行创建.大致的语法如下: 1 -- 使用master数据库 2 use master 3 -- 创建数据库 4 create datebase [架构名.]数据库名 5 on [primary]--主文件数据描述 6 ( 7 name = '数据库逻辑名', --一般是数据库的名称 8 filename = '数据文件的名字',--全路径 9 size = 12mb, --数据文件

Windows 已在 数据结构_顺序表.exe 中触发一个断点——new和delete注意事项

实现数据结构的顺序表的类时,输入,改,删,查都可以,但是最后析构函数时持续出错 错误提示"Windows 已在 数据结构_顺序表.exe 中触发一个断点" int *elem=new int(LIST_INIT_SIZE); if(!elem)cout<<"overflow"<<endl; if(leng>LIST_INIT_SIZE) cout<<"error"; else {    length=le

kendo ui grid 创建一行数据多次添加(kendo ui grid datasource multiple create)

今天测试之前使用kendo ui grid 做的数据表格的时候发现了一个bug,我使用的是kendo ui grid 系统自带的自动添加数据和编辑数据的功能,每次添加完一条数据的时候继续添加的时候会发现之前添加的数据会重复添加.查看官方文档,文档说是dataSource schema model id 必须是唯一键,而且添加数据完成之后需要返回一个数据包含id,结果研究了半天没有找到问题所在. var crudServiceBaseUrl = "/NFC"; var dataSourc

c#添加事物(全部执行和带保存点的执行)

全部执行 protected void Button2_Click(object sender, EventArgs e) { // 执行事务 SqlConnection con = new SqlConnection(str); con.Open(); SqlTransaction tran = con.BeginTransaction(); try { SqlCommand cmd1 = new SqlCommand("INSERT INTO Code( name ) VALUES ( 'w

[转]轻松学习Ionic (四) 修改应用图标及添加启动画面(更新官方命令行工具自动生成)

本文转自:http://blog.csdn.net/zapzqc/article/details/42237935 由于Ionic更新了命令行工具,以后修改应用图标和添加启动画面就简单了,最新方法见最下方: 应用图标: 1.在整个项目所在文件夹下创建res文件夹,里边再分别创建两个文件夹android和ios. 2.针对Android平台:将我们的要替换的启动图标放如android文件夹下.可以分别起名为:mdpi.png(48*48),hdpi(72*72).xhdpi(96*96).xxhd

MFC动态创建控件(按钮)及添加消息响应

动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态控件: 为了对照,我们先来看一下静态控件的创建. 放置静态控件时必须先建立一个容器,一般是对话框,这时我们在对话框编辑窗口中,从工具窗口中拖出所需控件放在对话框中即可,再适当修改控件ID,设置控件属性,一个静态控件就创建好了,当对话框被显示时,其上的控件也会显示. 静态控件不需要调用Create()函数来创建. 而创建动态控件有很大不同,以下以按钮为例,看一下动态控件的创建过程: 1.建立控件I