windows为错误处理提供了很多函数。
首先除了GetLastError还有一个GetLastErrorEx函数。但是现在
GetLastErrorEx和GetLastError都是相同的了。所以GetLastErrorEx的第二参数被忽略了。
GetLastError函数来让我们检查函数操作时产生的错误。它使用一种叫做“线程本地存储区”(thread-local storage)的机制将相应的错误代码和主调线程关联到一起。
通常我们使用这个函数只需要类似下面这样就可以了。
HANDLE file = CreateFile(TEXT("C:\\test.txt"), 0, 0, nullptr, OPEN_EXISTING, 0, nullptr); DWORD dwResoult=GetLastError(); switch (dwResoult) { //... }
所有的错误码都在WinError中定义着(被Windows.h包括)。当然想全部记下来是不可能的只能边学习边积累了。
为了我们调试程序的方便visual studio为我们提供了相应的工具来查看错误码。
监视窗口
我们只需要打上断点然后在监视窗口(watch)写入下面伪变量就可以参考断点处的GetLastError返回的结果了。
很方便 还会自动翻译成我们的语言。
如果想了解玩什么监视串口玩什么会显示???可以参考下面链接(要vpn的)
https://stackoverflow.com/questions/4001023/what-do-question-marks-in-visual-studio-watch-window-signify
错误查找
windows 还有一个小工具可以查看相应错误码是什么意思
但是只能输入数字,不能输入宏哦。
相应的API
当然如果想实现上面的工具的话windows 也提供了相应的api。
首先我们要用GetLastError来获得错误码(DWORD值)。然后就用到下面的函数了
//下面是UNICODE版本的 WINBASEAPI _Success_(return != 0) DWORD WINAPI FormatMessageW( _In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) != 0, _At_((LPWSTR*)lpBuffer, _Outptr_result_z_)) _When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) == 0, _Out_writes_z_(nSize)) LPWSTR lpBuffer, _In_ DWORD nSize, _In_opt_ va_list *Arguments );
其实这个函数的功能是通过语言标识符来寻找相应的语言文本然后返回该文本。所以我们必须先翻译字符串,然后把并把翻译好的消息表(message table)资源嵌在.exe或者DLL模块的中。
如果希望穿件信息表可以使用Message Compiler(MC.exe)。或者上面错误查找工具的某块按钮
dwFlags
设置一些影响函数工作的标记。一般就是下面三个标记
lpSource
我们的消息表地址。如果使用系统的错误码的话设置为nullptr就行了。
dwMessageId
指出想要查找的错误码ID
dwLanguageId
使用什么语言来显示.
lpBuffer
翻译完的字符串存储的地方
nSize
如果没有设置FORMAT_MESSAGE_ALLOCATE_BUFFER值就会返回需要缓冲区的大小(和字符串处理函数一样)。如果设置了就会返回其中字符的多少个。
Arguments
为占位符提供信息
下面是我从msdn上拔下来的一个例子
#include#include void ErrorExit(LPTSTR lpszFunction) { // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, //MAKELANGID宏会把LANG_NEUTRAL,SUBLANG_DEFAULT揉成一个数,这个数就是0表示使用系统默认的语言 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the error message and exit the process lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); ExitProcess(dw); } void main() { // Generate an error if(!GetProcessId(NULL)) ErrorExit(TEXT("GetProcessId")); }
当我们想使用自己的错误码时可以使用SetLastError函数来设置错误码。但是请遵守下面的规定
错误代码的不同字段位:
错误代码的不同字段位: |
31–30
|
29
|
28
|
27–16
|
15–0
|
内容
|
严重性
|
Microsoft/
客户 |
保留
|
Facility
代码 |
异常代码
|
含义 |
0 =
成功 1 =
信息(提示) 2 =
警告 3 =
错误 |
0 = Microsoft
定义的代码 1 =
客户定义的代码 |
必须为 0 |
前 256个值由Microsoft保留 |
Microsoft/
客户定义的代码 |