过年前,从china-pub买的。一直也没有安下心来读。看今年找工作的境况,也不得不抓把紧了。也愿与c++博客的各位朋友分享我的学习心得。
步入主题。
这一章开篇介绍了windows函数的几种返回值:VOID,BOOL,HANDLE,PVOID,LONG/DWORD。让我们明白,仅仅通过返回值,我们是不能清楚函数调用为什么会失败的。
windows内部,函数检测到错误会采用什么机制呢?它是采用“线程本地存储区”的机制来讲相应的错误代码与“主调线程”关联到一起。它可以使不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况。
函数返回的时候,其返回值会指出已发生的一个错误。
我们查看具体是什么错误,在相应的函数执行完成后调用GetLastError()即可。
windows中,错误有三种表示:
一个消息ID(如ERROR_PATH_NOT_FOUND)
消息文本(如the system cannot find the path specified)
一个编号(尽量避免使用)
调试程序的时候,我们可以配置watch窗口,让它始终显示线程的上一个错误代码和错误的文本描述。如$err,hr。hr是要显示错误代码的消息文本。不过我在windows mobile的环境下没有成功,没有弄清楚为什么。
那么我们怎么在自己的程序中显示消息文本呢?文章介绍了利用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。通过以上的示例,我们就知道其相应的工作原理呢。
这本书的源码的下载地址:http://wintellect.com/Books.aspx
大家如果对windows 编程感兴趣的话,不妨下来看看。
posted on 2009-02-20 00:24
Sandy 阅读(2285)
评论(4) 编辑 收藏 引用 所属分类:
windows学习