在调用一个API函数以后,如果函数失败,通常可以紧接着调用另一个API函数“GetLastError”来返回一个错误代码,下面这个类可以根据Windows定义的错误代码,查找到用文字表示的错误信息: 00001: #ifndef _YHB_SYSERROR_INCLUDED_ 00002: #define _YHB_SYSERROR_INCLUDED_ 00003: 00004: #include <stdexcept> 00005: #include <string> 00006: 00007: namespace yhb { 00008: 00009: class SysError 00010: : public std::runtime_error 00011: { 00012: public: 00013: SysError(int err=0) 00014: : runtime_error(makeMsgFromErrorNum(err)) 00015: {} 00016: SysError(const char *customMsg, int err = 0) 00017: : runtime_error(makeMsgFromErrorNum(customMsg, err)) 00018: {} 00019: static std::string makeMsgFromErrorNum(unsigned err = 0); 00020: static std::string makeMsgFromErrorNum(const char *customMsg, unsigned err = 0); 00021: }; 00022: 00023: } // end of namespace 00024: 00025: #endif
SysError从std::runtime_error派生,因此可以被抛出并被作为std::exception捕获。
如果不想使用异常,也可以用它的两个静态方法来返回错误信息。
实现 00001: #include "StdAfx.h" 00002: #include "./SysError.h" 00003: #include <sstream> 00004: #include <LMErr.h> 00005: 00006: #define WIN32_LEAN_AND_MEAN 00007: #include <Windows.h> 00008: 00009: using namespace std; 00010: 00011: namespace yhb { 00012: 00013: /************************************************************************ 00014: 管理用LoadLibrary()加载的模块句柄 00015: ************************************************************************/ 00016: class Module { 00017: public: 00018: explicit Module(HMODULE handle=0) 00019: : handle_(handle) 00020: {} 00021: ~Module() { 00022: free(); 00023: } 00024: Module & operator = (HMODULE handle) { 00025: free(); 00026: handle_ = handle; 00027: return *this; 00028: } 00029: bool isValid() const { return 0!=handle_; } 00030: operator HMODULE() const { return handle_; } 00031: private: 00032: Module(const Module &); 00033: Module & operator = (const Module &); 00034: void free() { 00035: if (0!=handle_) { 00036: ::FreeLibrary(handle_); 00037: handle_ = 0; 00038: } 00039: } 00040: HMODULE handle_; 00041: }; 00042: 00043: /************************************************************************ 00044: SysError 00045: ************************************************************************/ 00046: string SysError::makeMsgFromErrorNum(unsigned err/* =0 */) { 00047: if (0==err) { 00048: err = GetLastError(); 00049: if (NOERROR==err) 00050: return "no error!"; 00051: } 00052: Module module; 00053: DWORD flag = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; 00054: if (err >= NERR_BASE && err <= MAX_NERR) { 00055: module = LoadLibraryExA("netmsg.dll", 0, LOAD_LIBRARY_AS_DATAFILE); 00056: if (module.isValid()) 00057: flag |= FORMAT_MESSAGE_FROM_HMODULE; 00058: } 00059: char buf[1024]; 00060: if (FormatMessageA(flag, static_cast<HMODULE>(module), 00061: err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00062: buf, sizeof(buf), 0)) 00063: { 00064: return buf; 00065: } else { 00066: ostringstream os; 00067: os << "Unknown error: " << err << " (0x" << hex << err << ')'; 00068: return os.str(); 00069: } 00070: } 00071: 00072: string SysError::makeMsgFromErrorNum(const char *customMsg, unsigned err/* =0 */) { 00073: string result(customMsg); 00074: result += ' '; 00075: result += makeMsgFromErrorNum(err); 00076: return result; 00077: } 00078: 00079: } //end of namespace
C++里一种比较常用的方法,是将资源封装成一个类,在析构的时候释放该资源,比如上面的Module,析构的时候调用FreeLibrary。
|