首页 > 代码库 > Windows核心编程读书笔记1

Windows核心编程读书笔记1

今天特别困啊,这是为什么?!!刚刚把第一章看了一下,困到不行,所以写blog清醒一下。

第一章标题是“错误处理”,看了之后吓了一跳,难道第一章就讲这么高大上的东西?!不是不是,我现在的理解是,这章主要还是带我们感受一下以后遇到问题如何知道这个问题的描述。

我们在使用函数后,总会有一个结果:失败也好,成功也好。而这个结果,最终还是要以标识的形式落在地上的,章节内主要讲的是返回LONG/DWORD类型的情况。每个函数最后会返回一个错误代码给调用线程。

技术分享

想要看返回的是啥,这里提供了一种方法:DWORD GetLastError();

在windows里面,有一个文件(WinError.h)存放了错误码列表,这个文件很大,只取一个元素出来参考一下就好了。

技术分享
//
// MessageId: ERROR_SUCCESS
//
// MessageText:
//
// The operation completed successfully.
//
#define ERROR_SUCCESS                    0L
技术分享

每个错误由三个元素组成:

一个错误Id,也就是上面的MessageId所标识的,也是宏;

一个是错误描述,也就是MessageText所标识的;

一个是编号。

建议使用Id而不是编号。

然后有一段话没看明白:一些Windows函数调用成功可能是缘于不同的原因。例如,创建一个具名事件内核对象时,以下两种情况均会成功:对象实际完成创建,或者存在一个同名的事件内核对象。应用程序也许需要知道成功的原因。为返回这种信息,Microsoft选择采用"上一个错误代码"(last error code)机制。所以,特定函数调用成功时,可以调用GetLastError来确定额外的信息。对于具有这种行为的函数,Platform SDK文档会清楚指明能以这种方式调用GetLastError。文档中提供了CreateEvent函数的一个例子;如果已经存在具名事件,就返回ERROR_ALREADY_EXISTS。(以后懂了再回头看吧)

我们可以通过调试窗口来查看上一个错误代码以及文本描述,我试了一下,的确可以的。

 

技术分享

还有vs自带的小工具,error look up:

技术分享

下面就来看一下获得文本描述的关键函数:

1
2
3
4
5
6
7
8
DWORD FormatMessage(
    DWORD dwFlags,
    LPCVOID pSource,
    DWORD dwMessageId,
    DWORD dwLanguageId,
    PTSTR pszBuffer,
    DWORD nSize,
    va_list *Arguments);

  

FormatMessage可以支持多种语言,比如英语,汉语等,上面的例子中我们就看到了,返回的是汉语。

除了WinError.h中的代码,我们可以自定义错误代码返回:VOID SetLastError(DWORD dwErrCode);

技术分享

书中还给了我们一个例子:

技术分享

思路是获取用户输入的错误码,然后获取系统语言(中文,英文),然后利用FormatMessage将查询结果返回。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
case IDOK:
  // Get the error code
  DWORD dwError = GetDlgItemInt(hwnd, IDC_ERRORCODE, NULL, FALSE);
  HLOCAL hlocal = NULL;   // Buffer that gets the error message string
  // Use the default system locale since we look for Windows messages.
  // Note: this MAKELANGID combination has 0 as value
  DWORD systemLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  // Get the error code‘s textual description
  BOOL fOk = FormatMessage(
     FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
     FORMAT_MESSAGE_ALLOCATE_BUFFER,
     NULL, dwError, systemLocale,
     (PTSTR) &hlocal, 0, NULL);
  if (!fOk) {
     // Is it a network-related error?
     HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL,
        DONT_RESOLVE_DLL_REFERENCES);
     if (hDll != NULL) {
        fOk = FormatMessage(
           FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS |
           FORMAT_MESSAGE_ALLOCATE_BUFFER,
           hDll, dwError, systemLocale,
           (PTSTR) &hlocal, 0, NULL);
        FreeLibrary(hDll);
     }
  }
  if (fOk && (hlocal != NULL)) {
     SetDlgItemText(hwnd, IDC_ERRORTEXT, (PCTSTR) LocalLock(hlocal));
     LocalFree(hlocal);
  else {
     SetDlgItemText(hwnd, IDC_ERRORTEXT,
        TEXT("No text found for this error number."));
  }
  break;

dwError变量记录的就是错误码;

hlocal是记录描述字符串的;

systemLocale是指出要用什么语言来显示文本描述,根据两个特定的常量(即LANG_NEUTRAL和SUBLANG_NEUTRAL)来生成语言标识符,这两个常量联合到一起将生成一个0值--即操作系统的默认语言;

下面就来看FormatMessage中传递的参数吧:

FORMAT_MESSAGE_FROM_SYSTEM:我们希望获得与一个系统定义的错误代码对应的字符串,

FORMAT_MESSAGE_ALLOCATE_BUFFER:要求该函数分配一块足以容纳错误文本描述的内存。此块内存的句柄将在hlocal变量中返回,

FORMAT_MESSAGE_IGNORE_INSERTS:允许我们获得含有%占位符的消息。这些占位符将被Windows用来提供更多上下文相关信息;

技术分享

第三个参数指出想要查找的错误代码;

第四个参数指出要用什么语言来显示文本描述;

fOK记录是否查询成功,如果查询失败,则判断该错误是否与网络有关(这里暂时也不懂),否则就可以输出了。

总结

通过这一章大概了解如何自定义错误代码,以及如何通过错误码获取错误描述。请选中你要保存的内容,粘贴到此文本框

Windows核心编程读书笔记1