当许多系统函数失败时,他们设置的最后一个错误代码。如果您的应用程序需要更多详细信息的错误,它可以检索使用GetLastError函数的最后一个错误代码,并使用FormatMessage函数显示错误的描述。
DWORD WINAPI FormatMessage( __in DWORD dwFlags, __in LPCVOID lpSource, __in DWORD dwMessageId, __in DWORD dwLanguageId, __out LPTSTR lpBuffer, __in DWORD nSize, __in va_list* Arguments );
#include <windows.h> #include <strsafe.h> void ErrorExit(LPTSTR lpszFunction) { // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the error message and exit the process lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); ExitProcess(dw); } void main() { // Generate an error if(!GetProcessId(NULL)) ErrorExit(TEXT("GetProcessId")); }
①函数选项dwFlags分别为:
FORMAT_MESSAGE_ALLOCATE_BUFFER由函数分配输出缓冲区,
FORMAT_MESSAGE_FROM_SYSTEM表示程序将会在系统消息表资源中搜索所需消息,
FORMAT_MESSAGE_IGNORE_INSERTS程序将会忽略搜索到消息中的插入序列。
②lpSource值为NULL,并没有模块值和字符串直接传入所以为NULL,详细看以上各参数解析。
③dwMessageId为dw,即GetLastError的返回值。就是消息资源的ID号。
④dwLanguageId 设置为本地操作系统默认语言
⑤lpBuffer 输出缓冲区这里注意&,为什么要&呢? 因为 LPVOID lpMsgBuf只是一个指针对象,那么要必须要把它的地址传给lpBuffer参数。
注意:由于lpBuffer这个参数的值是FormatMessage函数动态分配的缓冲区,所以在不使用的时候要LocalFree.
void DisplayErrorText(DWORD dwLastError) { HMODULE hModule = NULL; // default to system source LPSTR MessageBuffer; DWORD dwBufferLength; DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM ; // If dwLastError is in the network range, load the message source. if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) { hModule = LoadLibraryEx( TEXT("netmsg.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE ); if(hModule != NULL) dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; } // Call FormatMessage() to allow for message text to be acquired from the system or from the supplied module handle. if(dwBufferLength = FormatMessageA( dwFormatFlags, hModule, // module to get message from (NULL == system) dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPSTR) &MessageBuffer, 0, NULL )) { DWORD dwBytesWritten; // Output message string on stderr. WriteFile( GetStdHandle(STD_ERROR_HANDLE), MessageBuffer, dwBufferLength, &dwBytesWritten, NULL ); // Free the buffer allocated by the system. LocalFree(MessageBuffer); } // If we loaded a message source, unload it. if(hModule != NULL) FreeLibrary(hModule); }
HANDLE GetStdHandle(DWORD nStdHandle);
GetStdHandle()返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄。
其参数nStdHandle的值为下面几种类型的一种:
值 含义
STD_INPUT_HANDLE 标准输入的句柄
STD_OUTPUT_HANDLE 标准输出的句柄
STD_ERROR_HANDLE 标准错误的句柄
实例程序:
实现一个彩色的Hello World!
#include <windows.h> //GetStdHandle和SetConsoleTextAttribute在头文件windows.h中 #include <iostream> using namespace std; void SetColor(unsigned short ForeColor=3,unsigned short BackGroundColor=0) //给参数默认值(缺省参数的函数),使该函数可以接受0/1/2个参数 { HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //本例以输出为例 SetConsoleTextAttribute(hCon,ForeColor|BackGroundColor); } int main() { SetColor(); std::cout<<"Hello world!"<<endl; SetColor(40,30); std::cout<<"Hello world!"<<endl; std::cout<<"Hello world!"<<endl; return 0; }
procedure TForm1.Button1Click(Sender: TObject); const ErrorTextBufLength = 256; var sErrorText: array [0 .. ErrorTextBufLength] of char; begin ZeroMemory(@sErrorText, ErrorTextBufLength); LoadLibrary('xxxx '); // 利用这句产生一个错误 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, GetLastError, 0, sErrorText,ErrorTextBufLength, nil); ShowMessage(String(sErrorText)); end;