2010-04-27 95 views
3

我有幾十個通過COM接口公開的對象,每個對象都有很多方法,總共有幾百個方法。這些接口將業務對象從我的應用程序展示給腳本引擎。保護COM接口免受例外

我已經被賦予了保護這些方法中的每一個方法免受異常的任務(使用COM的Error()函數來捕獲它們並返回一個錯誤,順便說一句,我找不到任何文檔,因爲這是不可能的)。就我的理解而言,這要求我在這些方法的每一個的內臟周圍添加一個try/catch。對於這幾百種方法中的每一種來說,catch塊都是相似或相同的,這些方法強烈地感染了一個問題(大量違反了DRY原則),但我想不出任何方法來避免改變每種方法。據我所知,這些方法是由COM直接調用的,沒有中間代碼,我可以用它來捕獲異常。我目前最好的想法是爲catch塊創建一個宏,但它有它自己的代碼嗅覺。任何人都可以想出更好的方法嗎?

順便說一下,我的應用程序的異常不會從std :: exception中派生出來,所以如果有一些COM自動處理標準異常的方法,它將無濟於事。而且我很遺憾不能改變現有的從std :: exception派生的異常。

回答

3

最可靠的C++方法是在這裏使用宏。我已經準備好接受這種說法,但我們多年來一直在使用這個解決方案,至今還沒有看到任何嚴重的問題。

定義一個用於清除IErrorInfotry {的「開始方法」宏,併爲} catch和錯誤處理定義「結束方法」。如果你正確地設計宏 - 把除了最必要的錯誤處理代碼之外的所有東西都放到輔助函數中,它將是一個可以容忍並且可靠的解決方案,它具有清晰的中等維護代碼。

是的,那doesn't look good at all,但至少它是可靠和符合標準的方式來實現你想要的。

0

Comet是大大簡化所涉及工作的一種方法。

+0

看起來很有趣,但對於這個遺留系統,我認爲這將是一個不可能的巨大工作量開始使用。如果我不幸設計出一個使用COM的新系統,我會記住它。 – rmeador 2010-04-27 19:40:00

0

鑑於所有COM接口方法都使用__stdcall約定,並假設您可以自己創建COM對象,您可以「簡單地」創建一個包裝COM對象,該對象返回通過QueryInterface包裝的COM接口。這個包裝的COM接口應該是一個COM接口,其中每個vtable條目都被替換爲包裝原始vtable函數try/catch的thunk。

我實際上並不建議這樣做,但這是一種方法,可以使執行COM對象的運行時間與外部系統絕緣。

+0

你有一個鏈接或示例代碼如何做到這一點? C++是否允許您以這種方式修改vtable,或者您是否需要使用一些直接的內存操作?難道它不是架構和操作系統的依賴(這可能會引起我的老闆「不」)? – rmeador 2010-04-27 20:05:43

3

這裏沒有快樂的答案。讓C++或SEH異常終止COM方法是非法的。你必須必須捕捉它們並將它們翻譯成合適的HRESULT。您的coclass必須實現ISupportsErrorInfo和IErrorInfo接口,以便客戶端可以返回異常信息。 CLR將很快這樣做來產生定製的異常消息。

您提到的Error()方法很可能是ATL CComCoClass::Error() method。它設置IErrorInfo將返回的異常信息。

沒有機制注入單個try/catch塊來捕獲所有可能的異常,COM方法直接從客戶端調用。您必須爲每個調用可引發異常的C++代碼的單個COM方法這樣做。不愉快的,但是這應該在編寫代碼時完成。您可能需要將它們中的每一個包裝起來,因爲找出它是否正在調用可能拋出的代碼是很困難的。

從技術上講,你可以改變類工廠來創建一個包裝器,它實現了接口的每個方法並委託給實際的方法。使用樣板試用/抓取處理程序。非常機械的,你可能會想出一些宏來減輕打擊。

+0

或者也許SetErrorInfo(),這很可能是ATL方法包裝的。 http://msdn.microsoft.com/en-us/library/aa910593(v=MSDN.10).aspx – 2010-04-28 05:56:41