Windows核心编程学习笔记一

 1.   当一个Windows函数检测到一个错误时,它会使用一个称为线程本地存储器(thread-local storage)的机制,将相应的错误代码号码与调用的线程关联起来。这将使线程能够互相独立地运行,而不会影响各自的错误代码。当函数返回时,它的返回值就能指明一个错误已经发生。若要确定这是个什么错误,请调用

DWORD GetLastError();

2.   错误表示法:消息ID,消息文本,消息号码

3.  进行调试的时候,监控线程的最后错误代码是非常有用的。在Microsoft Visual studio 6.0中,Microsoft的调试程序支持一个非常有用的特性,即可以配置Wa t c h窗口,以便始终都能显示线程的最后错误代码的号码和该错误的英文描述。通过选定Wa t c h窗口中的一行,并键入“@ e r r, h r”,就能够做到这一点。观察图1 - 1,你会看到已经调用了C r e a t e F i l e函数。该函数返回I N VA L I D _ H A N D L E _ VA L U E(- 1)的H A N D L E,表示它未能打开指定的文件。但是Wa t c h窗口向我们显示最后错误代码(即如果调用G e t L a s t E r r o r函数,该函数返回的错误代码)是0 x 0 0 0 0 0 0 0 2。该Wa t c h窗口又进一步指明错误代码2是指“系统不能找到指定的文件。”你会发现它与Wi n E r r o r. h头文件中的错误代码2所指的字符串是相同的。

4. FormatMessage

DWORD FormatMessage(
  DWORD dwFlags,
  LPCVOID lpSource,
  DWORD dwMessageId,
  DWORD dwLanguageId,
  LPTSTR lpBuffer,
  DWORD nSize,
  va_list* Arguments
);
那么我们怎么在自己的程序中显示消息文本呢?文章介绍了利用FormatMessage函数。这里我也介绍一下这个函数的用法:
         (下面的介绍摘自:http://www.cppblog.com/bidepan2023/archive/2008/02/03/42433.html
         DWORD FormatMessage(
             DWORD dwFlags,
             LPCVOID lpSource,
             DWORD dwMessageId,
             DWORD dwLanguageId,
             LPTSTR lpBuffer,
             DWORD nSize,
             va_list* Arguments
             );

         dwFlags:
         # FORMAT_MESSAGE_ALLOCATE_BUFFER // 此函数会分配内存以包含描述字串。
         # FORMAT_MESSAGE_FROM_SYSTEM,  // 在系统的id映射表中寻找描述字串
         # FORMAT_MESSAGE_FROM_HMODULE  // 在其他资源模块中寻找描述字串
         # FORMAT_MESSAGE_FROM_STRING   // 消息ID是个字串,不是个DWORD
         #FORMAT_MESSAGE_IGNORE_INSERTS // 允许我们获得含有%占位符的消息,不传递这个标志,就必须在Arguments参数中提供这些占位符的信息
         通常为:FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM

         lpSource:
         # 指定了FORMAT_MESSAGE_FROM_HMODULE的话,此参数表示模块的HANDLE
         # 指定了FORMAT_MESSAGE_FROM_STRING的话,此参数表示id字串
         通常为:NULL

         dwMessageId:
         消息ID;如果指定FORMAT_MESSAGE_FROM_STRING,将被忽略。

         dwLanguageId:
         消息描述所用的语言
         通常为:0表示自动选择

         lpBuffer:
         #如果未指定FORMAT_MESSAGE_ALLOCATE_BUFFER,则为自己提供的缓冲区
         #否则为系统LocalAlloc分配,需要被用户LocalFree

         nSize:
         #如果未指定FORMAT_MESSAGE_ALLOCATE_BUFFER,则为自己提供的缓冲区大小
         #否则为系统LocalAlloc分配之最小缓冲区大小

         Arguments:
         通常不使用


例子:

void  ShowError()
{
    DWORD dwError 
= GetLastError();

    HLOCAL hlocal 
= NULL;

    
// 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);

    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))
    
{
        OutputDebugString((PCTSTR) LocalLock(hlocal));
        LocalFree(hlocal);
    }

}



      这个是书中的例子的代码,我只是将它归结为了一个函数ErrorShow。这样我们在一个函数的后面调用,直接可以知道错误的原因。不过环境我是在smart device 的DEBUG环境下调时的,OutputDebugString会输出相应的字符串。

      这个例子中同时展示了FormatMessage的两种用法。观察一下第二个参数就明白了。

      visual studio 也提供了一个查询错误的小工具,为Error Lookup。通过以上的示例,我们就知道其相应的工作原理呢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值