Windows のエラー文字列の取得
今回は Windows の GetLastError() などが返すシステムエラーコードに対応するエラー文字列を返す関数を作成します.
エラー文字列は例えば C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include などにある WinError.h というファイルに書かれているのですが,開発中に見るのは面倒だったり,実行時にエラー文字列を画面に出力したい場合もあると思うので,一度エラーコードを文字列に変換する関数を作っておけば楽になるでしょう.
以下に,エラーコードをエラー文字列に変換する私の実装例を紹介します.
error.hpp
#ifndef ERROR_HPP_20100711_ #define ERROR_HPP_20100711_ #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include <string> #include <windef.h> namespace error { const std::wstring getErrorMessage(DWORD error); const std::wstring getLastErrorMessage(); } #endif
error.cpp
#include <iomanip> #include <sstream> #include <windows.h> #include "error.hpp" namespace { class AutoLocal { public: explicit AutoLocal(HLOCAL local = nullptr) : local_(local) {} ~AutoLocal() { LocalFree(local_); } HLOCAL& get() { return local_; } private: HLOCAL local_; }; } const std::wstring error::getErrorMessage(DWORD error) { AutoLocal msg; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&msg.get()), 0, nullptr)) { return std::wstring(static_cast<wchar_t*>(msg.get())); } else { // 失敗したら適当にエラーコードを付けて返す std::wostringstream ostr; ostr << L"0x" << std::hex << std::setw(8) << std::setfill(L'0') << error; return ostr.str(); } } const std::wstring error::getLastErrorMessage() { return getErrorMessage(GetLastError()); }
error.cpp にシステムエラーコードを文字列に変換する関数 getErrorMessage() を実装しました.error.cpp をプロジェクトに加え(他のソースコードと一緒にコンパイル),error.hpp を include することにより getErrorMessage が使用可能になります.
getErrorMessage はエラーコードを受け取り,それを FormatMessage に渡すことによって文字列を取得します.FormatMessage に FORMAT_MESSAGE_ALLOCATE_BUFFER を指定した場合,バッファを LocalFree で解放する必要があることに注意して下さい(本サンプルではデストラクタで解放処理をしています).
また,getLastErrorMessage() は getErrorMessage() の引数に GetLastError() の戻り値を渡しているだけです.
以下のテストコードで getErrorMessage の動作を確認できます.
test.cpp
#include <windows.h> #include "error.hpp" int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) { MessageBox(nullptr, error::getErrorMessage(ERROR_OUTOFMEMORY).c_str(), L"ERROR_OUTOFMEMORY に対応するエラー文字列", MB_OK); // この操作を完了するのに十分な記憶域がありません。 MessageBox(nullptr, error::getLastErrorMessage().c_str(), L"GetLastError() に対応するエラー文字列", MB_OK); // この操作を正しく終了しました。 return 0; }
nullptr でエラーが出る方は,nullptr をすべて 0 に置換して下さい.