Windows系統錯誤處理機制

1、什麼是錯誤程序員

意爲意爲不正確,與正確答案相反。咱們這裏講的是Windows操做系統裏進程運行時產生的錯誤。對咱們程序員來講,其實也就是咱們編程過程當中,調用Windows系統提供的API、COM 接口、內核驅動開發接口,這些API或接口失敗時產生的錯誤。這些錯誤會致使咱們的程序代碼完成不了預設的功能或效果。編程

2、Windows 錯誤機制windows

首先,Windows會爲各類API、接口失敗的各類錯誤預先定義好,一種錯誤用一個錯誤碼(Error Code)來表示。當錯誤產生時,API或接口會失敗,有的是用返回值返回錯誤碼,同時也表示調用成功或失敗,好比COM接口;有的是用返回值表明成功或失敗,錯誤碼放在特定的區域,經過特定API去獲取,好比大部分Win32 API,它將錯誤碼存儲在線程局部存儲區裏,永遠記住最後一個錯誤碼 ;有的是用狀態碼做爲錯誤碼,好比內核驅動開發接口數組

Windows系統的錯誤機制,當進程產生非致命錯誤時,它不會改變線程的執行路徑,但這不表明對程序沒有影響。若是一個錯誤發生,咱們不處理,而讓程序繼續往下跑,可能會致使後面更嚴重的問題。那麼咱們在Windows上編程時,應該調用API和接口後,及時檢測是否失敗,若是失敗,檢測錯誤,看是什麼錯誤,作不一樣處理。bash

在咱們編程的過程種,常常遇到下面三種錯誤:ide

  • Win32 Error
  • COM Error
  • NTSTATUS

3、Windows 錯誤代碼(Error Code)工具

3.一、Windows錯誤代碼spa

由前面咱們知道常見的三種錯誤,他們都是經過錯誤代碼來表明不一樣錯誤消息,它是一個DWORD值,也就是32bit,那麼這個值得每一位或幾位表明什麼意思,Windows是有規定的,錯誤代碼域也就是說錯誤代碼的定義規則是怎樣的。操作系統

3.二、錯誤代碼的生成
3.2.一、編寫錯誤信息文本文件
應用程序能夠根據業務需求按照Windows錯誤代碼域的規則定義本身的錯誤碼, 自定義錯誤碼須要先編寫一個 錯誤信息文本文件。文件以.mc爲後綴,其語法相對來講比較簡單,該文件主要包括三部分,註釋、信息頭(Header Section)和信息體(Message Section)。
  • 註釋
    註釋是以分號(;)開頭的行,在編譯後生成的C/C++頭文件中,MC編譯器會去掉這些分號,也就是說,若是你要生成一些帶C/C++的註釋,在分號後再加入C/C++的註釋便可,如:
;#ifndef _YOUR_MESSAGE_ERROR_TEXT_ ;#define _YOUR_MESSAGE_ERROR_TEXT_ ;// C/C++單行註釋 ; ;/* ; ; C/C++塊註釋 ; ;*/ ;#endif 
  • 信息頭部(Header Section)
    信息頭部定義信息體中須要使用的一些名稱和語言標識,能夠包含如下0個或多個語法聲明。
語法 說明
MessageIdTypedef=type 聲明錯誤碼類型,該定義通常放到信息頭部最前面,type在消息頭文件(.h)中被使用。定義的類型(32位)必需要可以容納全部的錯誤碼。
SeverityNames=(name=number[:SymbolName]) 聲明錯誤等級集合,在30-31位中定義。能夠定義多個錯誤等級,以空格分隔。默認定義爲:
SeverityNames=(Success=0x0 Informational=0x1 Warning=0x2 Error=0x3) ;name是錯誤等級名稱,是在信息體中引用的名字。SymbolName是自定義的符號名,該符號編譯後會在頭文件中定義,具體見實例。
FacilityNames=(name=number[:SymbolName]) 聲明設備代碼集合,在16-27位中定義,能夠定義多個設備代碼,中間以空格分隔。若是29爲沒有標記爲1,則前256位系統保留使用,應用能夠在0x100-0xFFF中定義。name是設備代碼名稱,是在信息體中引用的名字。SymbolName是自定義的符號名,該符號編譯後會在頭文件中定義,具體見實例。
LanguageNames=(name=number:filename) 聲明語言集合,其中name語句名稱,是在信息體中須要引用的名字,能夠支持多種語言,中間以空格分隔。number是語言標識,filename是包含對應語言的文件名,不帶後綴,由MC編譯器生成一個指定文件名加.bin的文件,用於存儲對應語言的錯誤文本信息。語言標識(language identifier)由一個16bit的數組成,其中高6位是次語言標識(SubLanguage ID), 低10位是主語言標識(Primary Language ID)。關於語言標識的常量定義在這裏。好比我要定義簡體中文,主語言標識爲0x04,次語言標識爲0x02,故簡體中文的語言標識爲0x804,因而能夠這樣定義:
LanguageNames=(Chinese=0x804:MSG00804)
  • 錯誤信息體(Message Section)
    信息體在信息頭以後定義,下表是一個信息體可能包含的一些定義,每一個信息體以MessageId開頭,以單獨成行的句點結束。Severity和Facility可選。
語法 說明
MessageId=[number|+number] 消息標識,必需要定義,但其值是可選的,若是沒有定義值,將使用上一個消息id加1。若是使用了+號,消息標識爲在上一個消息id上加指定的number。所定義的消息標識大小不能超過16位;
Severity=name 錯誤等級,若是Severity=Error;
Facility=name 設備代碼,如Facility=Application;
SymbolicName=name 符號名稱,該名稱會被定義在C/C++頭文件中,格式如:
#define name ((type)0xnnnnnnnn);其中type在信息頭MessageIdTypedef中聲明;
Language=name 信息語言,語言名稱在信息頭部定義,若是沒定義默認爲English。 如:Language=Chinese
message text 信息對應語言的文本;
. 以一個獨立成行的句點做爲信息體結束符;

若是一個信息體支持多種語言,對每一種語言都須要一個語言聲明、語言文本和獨立成行的句點,如:線程

MessageId=0x1
Severity=Error
Facility=Runtime
SymbolicName=MSG_BAD_COMMAND
Language=English
You have chosen an incorrect command. . Language=Chinese <Chinese message string goes here> 
3.2.二、編譯(MC.exe)
編寫好錯誤信息文本文件以後須要用Message Compiler(MC.exe)編譯工具進行編譯,mc的具體用法見 這裏。因爲咱們須要支持中文,因此須要指定-u參數,另外,若是咱們想爲設置29位爲1,須要指定-c參數,如:

mc.exe -cu MessageTable.mc

編譯成功後會生成四個文件:MessageTable.h、MessageTable.rc、MSG00409.bin、MSG00804.bin
其中MessageTable.h的內容以下:

#ifndef _ERROR_MESSAGE_TEXT_ #define _ERROR_MESSAGE_TEXT_ // // Values are 32 bit values laid 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_TEST_3 0x101 #define FACILITY_TEST_2 0x101 #define FACILITY_TEST_1 0x100 // // Define the severity codes // #define ITEST_SEVERITY_WARNING 0x2 #define TEST_SEVERITY_SUCESS 0x0 #define ITEST_SEVERITY_INFORMATIONAL 0x1 #define TEST_SEVERITY_ERROR 0x3 // // MessageId: TEST_E_01 // // MessageText: // // Define english string error message for TEST_E_01 // #define TEST_E_01 ((HRESULT)0xE1000001L) // // MessageId: TEST_E_02 // // MessageText: // // Define english string error message for TEST_E_02 // #define TEST_E_02 ((HRESULT)0xE1000002L) // // MessageId: TEST_E_03 // // MessageText: // // Define english string error message for TEST_E_03 // #define TEST_E_03 ((HRESULT)0xE1000003L) #endif 

注意,在生成的頭文件中發現沒有錯誤信息的中文文本說明,因爲生成的頭文件中只展現第一個定義的語言文本說明,若是想展現中文說明的話,在信息體把中文定義放在第一位就好了。如:

MessageId=0x1 Severity=Error Facility=TestFacility1 SymbolicName=TEST_E_01 Language=Chinese 在這兒定義TEST_E_01的中文錯誤文本 . Language=English Define english string error message for TEST_E_01

更多參考:https://www.jianshu.com/p/04a4ace9a31d

相關文章
相關標籤/搜索