過年前,從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.shnenglu.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 閱讀(2325)
評論(4) 編輯 收藏 引用 所屬分類:
windows學習