Date

一部を除く全てCOMメソッドはHRESULT型という32ビットの整数で結果を戻す。戻り値には成否(成功・失敗)や、その詳細情報が格納されている。

どの値が返るかはメソッドの実装による。成功であればS_OK、失敗であればE_FAILが代表的な値ですが、成否と詳細情報が一つの値に格納されているため判別には次のようなコードは使えない。

1
2
3
4
5
6
if(hr==S_OK) {
 /*成功した場合*/
}
else if(hr==E_FAIL) {
 /*失敗した場合*/
}

判別するにはSUCCEEDEDマクロとFAILEDマクロを使う。

1
2
3
4
5
6
if(SUCCEEDED(hr)){
 /*成功した場合*/
}
else if(FAILED(hr)) {
 /*失敗した場合*/
}

IUnknown::AddRefおよびIUnknown::Releaseは、HRESULT値ではなく参照カウントを返すことに注意すること。

文字列を取得する

HRESULT値は単なる32ビットの整数なので、そのままウォッチしただけでは分かりづらい。フレンドリな文字列を取得するためのAPIを使えばデバッグが容易になる。

dxerr9のAPIを使う

dxerr9のAPIを使う。S_OKE_FAILといったマクロ名と理由を取得できる。dxerr9.libをリンクする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// dxerr9 の API を使う
void HrToStrByDxErr(HRESULT hr) {
    TCHAR szMsg[MAX_ERROR_TEXT_LEN+MAX_PATH+256];
    _snwprintf_s(szMsg, _countof(szMsg), _TRUNCATE,
        TEXT("HRESULT=%08X (%s) ErrStr=%s Desc=%s\n")
        , hr
        , (FAILED(hr)) ? TEXT("FAILED") : TEXT("SUCCEEDED")
        , DXGetErrorString9(hr), DXGetErrorDescription9(hr));
    OutputDebugString(szMsg);
}

AMGetErrorTextを使う

DirectShowのAPIを使う。Quartz.libをリンクする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// AMGetErrorText を使う
void HrToStrByAMGet(HRESULT hr) {
    TCHAR szErr[MAX_ERROR_TEXT_LEN];
    TCHAR szMsg[MAX_ERROR_TEXT_LEN+MAX_PATH+256];
    // MAX_ERROR_TEXT_LEN は errors.h で定義済み
    AMGetErrorText(hr,szErr,MAX_ERROR_TEXT_LEN);
    _snwprintf_s(szMsg, _countof(szMsg), _TRUNCATE,
        _T("HRESULT=%08X (%s) %s")
        , hr
        , (FAILED(hr)) ? TEXT("FAILED") : TEXT("SUCCEEDED")
        , szErr);
    OutputDebugString(szMsg);
}

FormatMessageを使う

Win32のAPIを使う。FormatMessageGetLastErrorの値から文字列を得るAPIだがHRESULT値も解釈できる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// FormatMessage を使う
void HrToStr(HRESULT hr) {
    LPVOID string;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM,
                  NULL,
                  hr,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  (LPTSTR)&string,
                  0,
                  NULL);
    if (string != NULL)
        OutputDebugString((LPCWSTR)string);
    LocalFree(string);
}

どれを使うか

  • DirectX9アプリケーションであればDxErr9を使う。
  • DirectGraphicsやDirectSoundなどを使わない単なるDirectShowアプリケーションまたは単体のDirectShowフィルタ(DLL)であればAMGetErrorTextを使う。
  • 単なるWin32アプリケーションであればFormatMessageを使う。

たとえばDirectX9固有のエラーメッセージはAMGetErrorTextでは取得できませんがDxErr9のDXGetErrorString9はDirectShowのエラーメッセージを取得できる。だからといって何も考えずにDXGetErrorString9を使うと余計な依存関係が生まれてしまう。

プロジェクトで使っているAPIで使い分けると良いだろう。

https://github.com/mahorigahama/ShowErrMsg


Comments

comments powered by Disqus