向自己的模块添加错误代码

原文链接:https://blog.csdn.net/s634772208/article/details/46402677

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

 

一、MC工具介绍

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

当编写完成一个*.mc文件之后,为了在程序中使用这个文件,你需要一些操作。首先,使用MC工具将这种文件编译成一个*.rc文件(还会生成*.h*.bin文件);然后将*.rc*.h添加进相应的DLLEXE)模块中编译;最后通过相应的事件日志函数或者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])----设置消息码中第3130位,即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标识了一个消息定义的开始,必须存在,SeverityFacility声明是可选的。

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

 

[cpp]  view plain  copy
  1. ;//***** Sample.mc *****  
  2.   
  3. ;//This is the header section.  
  4.   
  5. MessageIdTypedef=DWORD  
  6.   
  7. SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS  
  8.     Informational=0x1:STATUS_SEVERITY_INFORMATIONAL  
  9.     Warning=0x2:STATUS_SEVERITY_WARNING  
  10.     Error=0x3:STATUS_SEVERITY_ERROR  
  11.     )  
  12.   
  13.   
  14. FacilityNames=(System=0x0:FACILITY_SYSTEM  
  15.     Runtime=0x2:FACILITY_RUNTIME  
  16.     Stubs=0x3:FACILITY_STUBS  
  17.     Io=0x4:FACILITY_IO_ERROR_CODE  
  18. )  
  19.   
  20. LanguageNames=(English=0x409:MSG00409)  
  21. LanguageNames=(Chinese=0x804:MSG00804)  
  22.   
  23. // The following are message definitions.  
  24.   
  25.   
  26. MessageId=0x1  
  27. Severity=Error  
  28. Facility=Runtime  
  29. SymbolicName=MSG_BAD_COMMAND  
  30. Language=English  
  31. You have chosen an incorrect command.  
  32. .  
  33. Language=Chinese  
  34. 你选择了一个不正常的命令。  
  35. .  
  36.   
  37. MessageId=0x2  
  38. Severity=Warning  
  39. Facility=Io  
  40. SymbolicName=MSG_BAD_PARM1  
  41. Language=English  
  42. Cannot reconnect to the server.   
  43. .  
  44. Language=Chinese  
  45. 无法连接服务器。  
  46. .  
  47.   
  48. MessageId=0x3  
  49. Severity=Success  
  50. Facility=System  
  51. SymbolicName=MSG_STRIKE_ANY_KEY  
  52. Language=English  
  53. Press any key to continue . . . %0   
  54. .  
  55. Language=Chinese  
  56. 按任意键继续...  
  57. .  
  58.   
  59.   
  60.   
  61. MessageId=0x4  
  62. Severity=Error  
  63. Facility=System  
  64. SymbolicName=MSG_CMD_DELETE  
  65. Language=English  
  66. File %1 contains %2 which is in error   
  67. .  
  68. Language=Chinese  
  69. 文件 %1 包含 %2 r损坏。  
  70. .  
  71.   
  72.   
  73. MessageId=0x5  
  74. Severity=Informational  
  75. Facility=System  
  76. SymbolicName=MSG_RETRYS  
  77. Language=English  
  78. There have been %1!d! attempts with %2!d!%% success%! Disconnect from the server and try again later.   
  79. .  
  80. Language=Chinese  
  81. 未知错误!无法连接服务器,请稍后重试!  
  82. .  

 

2、使用MC工具编译

打开visual studio的命令行界面,进入McFile.mc文件目录,使用命令mc -a -A McFile.mc进行编译,如下:

 

 

编译成功后,会在当前目录下生成McFile.hMcFile.rcMSG00409.binMSG00804.bin四个文件,因为文本文件中支持中英文,所以生成了两个*.bin文件。

 

McFile.h文件部分预览如下:

[cpp]  view plain  copy
  1. //***** Sample.mc *****  
  2. //This is the header section.  
  3. // The following are message definitions.  
  4. //  
  5. //  Values are 32 bit values layed out as follows:  
  6. //  
  7. //   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1  
  8. //   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  
  9. //  +---+-+-+-----------------------+-------------------------------+  
  10. //  |Sev|C|R|     Facility          |               Code            |  
  11. //  +---+-+-+-----------------------+-------------------------------+  
  12. //  
  13. //  where  
  14. //  
  15. //      Sev - is the severity code  
  16. //  
  17. //          00 - Success  
  18. //          01 - Informational  
  19. //          10 - Warning  
  20. //          11 - Error  
  21. //  
  22. //      C - is the Customer code flag  
  23. //  
  24. //      R - is a reserved bit  
  25. //  
  26. //      Facility - is the facility code  
  27. //  
  28. //      Code - is the facility's status code  
  29. //  
  30. //  
  31. // Define the facility codes  
  32. //  
  33. #define FACILITY_SYSTEM                  0x0  
  34. #define FACILITY_STUBS                   0x3  
  35. #define FACILITY_RUNTIME                 0x2  
  36. #define FACILITY_IO_ERROR_CODE           0x4  
  37.   
  38.   
  39. //  
  40. // Define the severity codes  
  41. //  
  42. #define STATUS_SEVERITY_WARNING          0x2  
  43. #define STATUS_SEVERITY_SUCCESS          0x0  
  44. #define STATUS_SEVERITY_INFORMATIONAL    0x1  
  45. #define STATUS_SEVERITY_ERROR            0x3  
  46.   
  47.   
  48. //  
  49. // MessageId: MSG_BAD_COMMAND  
  50. //  
  51. // MessageText:  
  52. //  
  53. //  You have chosen an incorrect command.  
  54. //  
  55. #define MSG_BAD_COMMAND                  ((DWORD)0xC0020001L)  


 

3、将生成的资源文件编译进dll(exe)模块中。

创建一个WIN32DLL工程,将McFile.hMcFile.rc文件添加进去,进行编译,生成相应的dll即可提供给我们的程序使用。

 

四、使用自己定义的错误代码,即第三步生成的消息资源模块

 

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <windows.h>  
  3.   
  4. using namespace std;  
  5.   
  6.   
  7. //  
  8. #ifdef _UNICODE  
  9. #define COUT wcout  
  10. #else  
  11. #define COUT cout  
  12. #endif  
  13.   
  14.   
  15. int main()  
  16. {  
  17.     DWORD dwError = 0;  
  18.   
  19.     DWORD dwLanguageId = MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL );  
  20.   
  21.     //解决问题:wcout输出时显示不了中文  
  22.     COUT.imbue( std::locale( "chs" ) );  
  23.   
  24.     HLOCAL lpMsgTextBuf = NULL;  
  25.     COUT << TEXT("输入一个自定义的错误代码(如:3221356545(0xC0020001) ):");  
  26.     while( cin >> dwError )  
  27.     {  
  28.         lpMsgTextBuf = NULL;  
  29.   
  30.         HMODULE ghResDll = LoadLibrary( TEXT("WinMsgDll.dll") );  
  31.         if ( NULL == ghResDll )  
  32.         {  
  33.             COUT << TEXT("加载消息模块失败!") << endl;  
  34.             return -1;  
  35.         }  
  36.   
  37.   
  38.         BOOL bOk = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |   
  39.             FORMAT_MESSAGE_IGNORE_INSERTS |   
  40.             FORMAT_MESSAGE_ALLOCATE_BUFFER,  
  41.             ghResDll, dwError, dwLanguageId, (LPTSTR)&lpMsgTextBuf, 0, NULL );  
  42.   
  43.   
  44.         if ( !bOk )  
  45.         {  
  46.             COUT << TEXT("error ") << GetLastError() << endl;  
  47.         }  
  48.   
  49.         if ( NULL != lpMsgTextBuf )  
  50.         {  
  51.             COUT << (LPTSTR)lpMsgTextBuf << endl;  
  52.             LocalFree( lpMsgTextBuf );  
  53.         }  
  54.   
  55.         COUT << TEXT("输入一个自定义的错误代码(如:3221356545(0xC0020001) ):");  
  56.     }  
  57.     return 0;  
  58. }  

猜你喜欢

转载自blog.csdn.net/a812073479/article/details/79688218