2012-04-16 21 views
3

要遵循典型的COM程序,每當出現任何錯誤,必須做到以下幾點:如何在C++中調用COM時包裝錯誤?

  1. 檢查HRESULTFAILED或類似的,看看是否有錯誤發生。
  2. 創建一個變量來保存一個IErrorInfo(通常CComPtr<IErrorInfo>
  3. 呼叫::GetErrorInfo(0, &var)
  4. Get the human readable version of that by calling IErrorInfo::GetDescription.
  5. BSTR轉換爲std::wstring
  6. std::wstring轉換爲某種形式的char const*
  7. 拋出一個用戶定義的異常類型,它來自std::exception,它揭示了上面的第1,5和6位。

這一切看起來都像是很多樣板,它必須圍繞COM中的每個函數調用。我知道MSVC++編譯器提供了一大堆東西來使COM更容易搞亂,比如ATL和編譯器特定的COM擴展_com_error,_com_raise_error和類似的,但我不確定如何使用這些,或者如果他們甚至打算被用戶代碼使用。

是否有任何典型的策略用於以異常安全和競爭條件安全的方式管理這種複雜性?

+1

從#import指令開始,其餘部分自動放置到位。 – 2012-04-16 01:04:56

+0

@HansPassant:我沒有針對相關目標的類型庫。 (所有我是'wbemidl.h') – 2012-04-16 01:10:37

+1

然後fuggedaboudid,你必須自己包裹。只需編寫一個CheckHR()函數。 – 2012-04-16 01:22:56

回答

4

「明顯的」解決方案是ComException。它可以處理幾乎所有的步驟 - 你只需要得到得到HRESULT的構造函數,並拋出生成的對象(步驟1和7)。

你甚至可以編寫

HRESULT check(HRESULT hr) 
{ 
    if(FAILED(hr)) throw ComException(hr); 
    return hr; // Success comes in different forms. 
} 

照顧第7步的爲您服務。例如。 check(pUnk->QueryInterface(MyID, &pMyIf));

+0

這將不會查詢IErrorInfo – 2012-04-16 08:31:44

+0

@AlexandreC。 :這會在'ComException :: ComException(HRESULT)'中發生。 – MSalters 2012-04-16 10:54:37

+0

ComException如何檢索指向IErrorInfo的指針?你必須以某種方式向它傳遞一個指向你從第一個地方調用函數的接口,不是嗎? – 2012-04-16 11:59:11

1

恐怕沒有爲您提供的半標準方式,即使您在msdn上查看示例應用程序和api用法,他們都表示您必須手動執行所有繁瑣的HResult檢查,檢查是否IPtr是有效的等等。你將不得不編寫你自己的函數來包裝所有這些,這樣你就不會重複代碼,它不應該成爲一個問題。