windows核心编程 第1章 错误处理

好吧,我承认我是个很懒的人,很多内容是从别人那里复制的。。。不过加了自己的实践,有意外的地方,以后的实验的环境默认为win7x64,Visual Studio 2008,红色的一般是我出意外的地方=_=
主要参考:http://www.cppblog.com/SpringSnow/archive/2009/02/20/74350.html

       这一章开篇介绍了windows函数的几种返回值:VOID,BOOL,HANDLE,PVOID,LONG/DWORD。让我们明白,仅仅通过返回值,我们是不能清楚函数调用为什么会失败的。windows内部,函数检测到错误会采用什么机制呢?它是采用“线程本地存储区”的机制来讲相应的错误代码与“主调线程”关联到一起。它可以使不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况。

错误代码:一个Windows函数返回的错误代码对了解该函数为什么会运行失败常常很有用。Microsoft公司编译了一个所有可能的错误代码的列表(存放在WinError.h头文件中),并且为每个错误代码分配了一个32位的号码;

线程本地存储器:thread-local storage,当一个Windows函数检测到一个错误时,它会使用一个称为线程本地存储器的机制,将相应的错误代码与调用的线程关联起来,这将使线程能够互相独立地运行,而不会影响各自的错误代码;

GetLastError函数:GetLastError函数返回一个32位的错误代码,它主要用于两种情况:1)确定是什么样的错误,此时当Windows函数运行失败时,应该立即调用GetLastError函数,如果调用了另一个Windows函数,它的值很可能被改写;2)搞清楚成功的原因是什么,有些Windows函数之所以能成功运行,其中的原因有很多,比如CreateEvent函数运行成功,既可能是因为你实际创建了该对象,也有可能是因为已经存在带有相同名字的事件内核对象,此时可以调用GetLastError函数可以搞清函数运行成功的原因;

SetLastError函数:SetLastError函数用于设定线程最后的错误代码,这个错误代码既可以是Windows系统自定义的(代码的第29位必须为0),也可以是用户自定义的(代码的第29位必须为1);

FormatMessage函数:FormatMessage函数用于将错误代码转换成它的文本描述;

         函数返回的时候,其返回值会指出已发生的一个错误。
         我们查看具体是什么错误,在相应的函数执行完成后调用GetLastError()即可。

         windows中,错误有三种表示:
         一个消息ID(如ERROR_PATH_NOT_FOUND)
            消息文本(如the system cannot find the path specified)
         一个编号(尽量避免使用)

         调试程序的时候,我们可以配置watch窗口,让它始终显示线程的上一个错误代码和错误的文本描述。如 $err,hr 。hr是要显示错误代码的消息文本。
windows核心编程。。。第1章错误处理 - 龙行天下 - 少年情
 
windows核心编程。。。第1章错误处理 - 龙行天下 - 少年情
 


         那么我们怎么在自己的程序中显示消息文本呢?文章介绍了利用FormatMessage函数。这里我也介绍一下这个函数的用法:
         
         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();
DWORD dwError = 5L;
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))
{
//这个输出可以在VS的“输出窗口 看到
               // LocalLock锁定一个本地内存项目 并且 返回一个指向内存块第一个Byte的指针
OutputDebugString((PCTSTR) LocalLock(hlocal));
//这里要把项目属性改为 多字节字符集,不然会出现乱码
cout<<(PCTSTR) LocalLock(hlocal)<<endl;
LocalFree(hlocal);
}
}

windows核心编程。。。第1章错误处理 - 龙行天下 - 少年情
 
windows核心编程。。。第1章错误处理 - 龙行天下 - 少年情
 
 visual studio 也提供了一个查询错误的小工具,为Error Lookup。通过以上的示例,我们就知道其相应的工作原理。在“工具”里可以找到。
windows核心编程。。。第1章错误处理 - 龙行天下 - 少年情
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值