ndows错误代码转换为错误信息

来源:岁月联盟 编辑:zhuzhu 时间:2007-01-16

在调用一个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。