ブログ@kaorun55

HoloLensやKinectなどのDepthセンサーを中心に書いています。

Win32例外

今のところ自分が作ったクラスの中で一番使ってるもの。


Windows APIのエラーコードをエラーメッセージに変換する例外クラス。

GetLastError()で取れるエラーコードと、多分HRESULTのエラーも取れると思う

#使用は自己責任で!!


では、おソース
Win32Exception.h

#if !defined( WINEXCEPTION_H_INCLUDE )
#define WINEXCEPTION_H_INCLUDE

// MFC使用時用にはwindows.hはインクルードしない
#if !defined( __AFXWIN_H__ )
 #include <windows.h>
#endif  // !defined( __AFXWIN_H__ )

#include <string>
#include <stdexcept>

/// Win32ラッパークラス群
namespace win32
{
    /// Win32例外クラス
    class Win32Exception : public std::runtime_error
    {
    public:

        // コンストラクタ
        Win32Exception( DWORD errorCode );
        Win32Exception( DWORD errorCode, const char *fileName, int lineNo );

        // デストラクタ
        ~Win32Exception();

        // エラーコードの取得
        DWORD getErrorCode() const;
        // エラーメッセージの取得
        const std::string& getErrorMessage() const;

        // エラーメッセージの取得
        const char* what() const;

        // エラーコードからエラーメッセージの取得
        static std::string getErrorMessage( DWORD errorCode );

    private:

        DWORD       errorCode_;     ///< エラーコード
        std::string errorMessage_;  ///< エラーメッセージ
    };
} // namespace win32

#endif  // !defined( WINEXCEPTION_H_INCLUDE )
// EOF


次にWin32Exception.cpp

#include "Win32Exception.h"
#include <sstream>

/// Win32ラッパークラス群
namespace win32
{
    /**
     * コンストラクタ
     *
     * @param dwResult エラーコード
     */
    Win32Exception::Win32Exception( DWORD errorCode )
        : std::runtime_error( "" )
        , errorCode_( errorCode )
        , errorMessage_( getErrorMessage( errorCode ) )
    {
    }

    Win32Exception::Win32Exception( DWORD errorCode, const char *fileName, int lineNo )
        : std::runtime_error( "" )
        , errorCode_( errorCode )
    {
        std::stringstream str;
        str << fileName << "(" << lineNo << "):" << getErrorMessage( errorCode );
        errorMessage_ = str.str();
    }

    /**
     * デストラクタ
     */
    Win32Exception::~Win32Exception()
    {
    }

    /**
     * エラーコードの取得
     *
     * @return エラーコード
     */
    DWORD Win32Exception::getErrorCode() const
    {
        return errorCode_;
    }

    /**
     * エラーメッセージの取得
     *
     * @return エラーメッセージ
     */
    const std::string& Win32Exception::getErrorMessage() const
    {
        return errorMessage_;
    }

    /**
     * エラーメッセージの取得
     *
     * @return エラーメッセージ
     */
    const char* Win32Exception::what() const
    {
        return errorMessage_.c_str();
    }

    /**
     * エラーコードからエラーメッセージの取得(クラス関数)
     *
     * @param dwErrCode エラーコード
     *
     * @return エラーメッセージ
     */
    std::string Win32Exception::getErrorMessage( DWORD errorCode )
    {
        // エラーメッセージ用クラス
        class ErrorMessage
        {
        public:

            ErrorMessage() : message_(0) {}
            ~ErrorMessage(){ if( message_ != 0 ) ::LocalFree( message_ ); }

            char** operator & (){ return &message_; }
            char* get(){ return message_; }

        private:

            char* message_;
        };

        ErrorMessage message; // メッセージバッファ

        // エラーメッセージの取得
        BOOL ret = ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                    FORMAT_MESSAGE_FROM_SYSTEM | 
                                    FORMAT_MESSAGE_IGNORE_INSERTS,
                                    0, errorCode,
                                    MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                                    (LPTSTR)&message, 0, 0 );

        return ret ? message.get() : "未定義エラー";
    }
}
// EOF


最後に使用例

#include <iostream>
#include "Win32Exception.h"

void main()
{
    try {
        // "ハンドルが無効です。"
        BOOL ret = ::ReadFile( 0, 0, 0, 0, 0 );
        if ( !ret ) {
            throw win32::Win32Exception( ::GetLastError() );
        }
    }
    catch ( std::exception& ex ) {
        std::cout << ex.what();
    }

    try {
        // "D:\win32exceptiontest\main.cpp(21):ハンドルが無効です。"
        BOOL ret = ::ReadFile( 0, 0, 0, 0, 0 );
        if ( !ret ) {
            throw win32::Win32Exception( ::GetLastError(), __FILE__, __LINE__ );
        }
    }
    catch ( std::exception& ex ) {
        std::cout << ex.what();
    }
}
// EOF


プリコンパイル済みヘッダを無効にすればMFCでも使えるのでオススメの一品です:)