Windows Programming/錯誤處理

維基教科書,自由的教學讀本

在Windows API函數中,一般返回值類型為如下幾種:

  • VOID,即C語言的void類型,表示該函數執行期間不會出任何錯誤,這種函數比較少;
  • BOOL,即C語言的int類型,返回TRUE(即1)表示函數執行期間沒有錯誤,返回FALSE(即0)表示函數執行期間出現錯誤;
  • HANDLE,即C語言的void*,一般返回NULL表示函數執行有錯誤,有時也會返回一個INVALID_HANDLE_VALUE(即指向0xFFFFFFFF),何時返回什麼值文檔中都有說明;
  • PVOID,即C語言的void*,返回NULL表示函數執行有錯誤;
  • LONG/DWOWD,即C語言裡的long/unsigned int類型,這種類型的值比較難於處理,要嚴格按照文檔說明進行判斷,一般來說,返回0表示程序執行無誤,否則需要根據返回值作具體判斷

GetLastError函數是在程序調用Win32 API函數出現錯誤時,獲取最後一次錯誤的編號,以便進一步確定具體錯誤原因。GetLastError函數返回一個整數,表示錯誤代碼,每個代碼的含義可以在頭文件WinError.h中找到申明。

例子[編輯]

#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <windows.h>
 
#define MAX_ERROR 512
 
int main(int argc, char* argv[])
{
	// 保存错误编号
	DWORD dwError = NO_ERROR;
   
	// 保存错误信息
	TCHAR szBuffer[MAX_ERROR] = TEXT("");
 
	// 保存文件句柄
	HANDLE hFile = INVALID_HANDLE_VALUE;
 
	// 调用C函数设置当前区域环境为中国
	_tsetlocale(LC_ALL, _T("zhi"));
 
	// 调用API打开一个文件(由于此文件不存在,所以该函数调用不成功)
	hFile = CreateFile(TEXT("c:/abc.dat"), 
		GENERIC_READ | GENERIC_WRITE, 
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);
 
	// 判断文件句柄是否有效,如无效,则调用GetLastError获取错误代码
	if (hFile == INVALID_HANDLE_VALUE) {
		dwError = GetLastError();
		_tprintf(_T("错误代码为: %d。/n"), dwError);
 
		// 根据GetLastError函数返回值判断错误原因
		if (dwError == ERROR_INVALID_NAME) {
			_tprintf(_T("错误代码显示错误原因为:文件名错误。/n"));
		}
	}
 
	if (dwError != NO_ERROR) {
		// 调用FormatMessage函数获取系统定义的错误信息
		DWORD nLen = FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,    // 设置消息来自于系统且忽略插入词
			NULL,            // 设置消息源,函数可以通过这个消息源格式化错误信息,此处不使用消息源,所以设置为NULL
			dwError,        // 错误编号
			0,                // 语言信息,0表示使用系统默认语言
			szBuffer,        // 存放错误信息的缓冲区
			MAX_ERROR,        // 缓冲区长度(最大字数)
			NULL            // 用于格式化信息的参数,这里为NULL
		);
	   
		if (nLen > 0) {
			_tprintf(_T("系统提示错误信息为: %s"), szBuffer);
		} else {
			_tprintf(_T("无法获取错误信息。"));
		}
	}
 
	system("pause");
	return 0;
}

FormatMessage的用法[編輯]

根據一個錯誤碼返回一個錯誤訊息。

DWORD FormatMessage(
    DWORD dwFlags,
    LPCVOID lpSource,
    DWORD dwMessageId,
    DWORD dwLanguageId,
    LPTSTR lpBuffer,
    DWORD nSize,
    va_list* Arguments
    );

dwFlags:

  1. FORMAT_MESSAGE_ALLOCATE_BUFFER // 此函數會分配內存以包含描述字串。
  2. FORMAT_MESSAGE_FROM_SYSTEM, // 在系統的id映射表中尋找描述字串
  3. FORMAT_MESSAGE_FROM_HMODULE // 在其他資源模塊中尋找描述字串
  4. FORMAT_MESSAGE_FROM_STRING // 消息ID是個字串,不是個DWORD

lpSource:

  1. 指定了FORMAT_MESSAGE_FROM_HMODULE的話,此參數表示模塊的HANDLE
  2. 指定了FORMAT_MESSAGE_FROM_STRING的話,此參數表示id字串

通常為:NULL

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

dwLanguageId: 消息描述所用的語言 通常為:0表示自動選擇

lpBuffer:

  1. 如果未指定FORMAT_MESSAGE_ALLOCATE_BUFFER,則為自己提供的緩衝區
  2. 否則為系統LocalAlloc分配,需要被用戶LocalFree

nSize:

  1. 如果未指定FORMAT_MESSAGE_ALLOCATE_BUFFER,則為自己提供的緩衝區大小
  2. 否則為系統LocalAlloc分配之最小緩衝區大小

Arguments: 通常不使用