2008-10-28 27 views
8

這是核心問題:我有一個在單獨的AppDomain中使用COM interop的.NET應用程序。 COM的東西似乎是加載程序集回到默認域,而不是COM的東西被調用的AppDomain。COM Interop是否尊重用於程序集加載的.NET AppDomain邊界?

我想知道的是:這是預期的行爲,還是我做錯了什麼導致這些COM相關的程序集加載到錯誤的AppDomain?請參閱下面的情況的更詳細的描述...

該應用程序包含3個程序集: - 主EXE,應用程序的入口點。 - common.dll,僅包含一個接口IController(IPlugin風格) - controller.dll,包含實現IController和MarshalByRefObject的Controller類。該類完成所有工作,並使用COM互操作與另一個應用程序進行交互。

主要EXE的相關部分看起來是這樣的:

AppDomain controller_domain = AppDomain.CreateDomain("Controller Domain"); 
IController c = (IController)controller_domain.CreateInstanceFromAndUnwrap("controller.dll", "MyNamespace.Controller"); 
result = c.Run(); 
AppDomain.Unload(controller_domain); 

的common.dll只包含這2兩件事:

public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun} 
public interface IController 
{ 
    ControllerRunResult Run(); 
} 

而且controller.dll包含這個類(也調用COM interop的東西):

public class Controller: IController, MarshalByRefObject 

當第一次運行應用程序時,Assembly.GetAssem blies()看起來和預期的一樣,在兩個AppDomain中都加載了common.dll,而controller.dll只加載到控制器域中。在調用c.Run()之後,我發現與COM互操作相關的程序集已經加載到默認的AppDomain中,而不是在COM互操作所在的AppDomain中。

爲什麼會發生這種情況?

如果你有興趣,這裏是一個有點背景:

本來這是一個1個AppDomain中的應用。它與COM接口的東西是一個服務器API,它在長時間的使用中不穩定。當COM事件發生COMException(沒有有用的診斷信息)時,整個應用程序必須在COM連接再次工作之前重新啓動。只需重新連接到COM應用程序服務器就會再次產生即時COM異常。爲了解決這個問題,我試圖將COM interop的東西移動到一個單獨的AppDomain中,這樣當發生神祕的COMExceptions時,我可以卸載它出現的AppDomain,創建一個新的並重新開始,而不必手動重新啓動應用程序。這是理論無論如何...

+0

fyi,如果其他人看一看 - 這是惠普質量中心API DLL給我這個問題。我通過讓應用程序自行重啓來解決它,但我仍然對這種情況發生的原因感興趣。 – Xiaofu 2009-05-30 03:33:18

回答

16

不幸的是,COM組件在進程空間中加載,而不是在AppDomain的上下文中加載。因此,您需要手動拆除(釋放和卸載)您的本機DLL(適用於COM和P/Invoke)。簡單地銷燬一個appdomain會對你沒有好處,但重新構建整個過程不應該是重置COM狀態所必需的(只需重新創建COM對象也應該正常工作,這聽起來像是組件提供者代碼中的一個錯誤,也許他們可以解決它?)

參考

(TechNet) Process Address Space

(MSDN) Application Domains

(MSDN) Boundaries: Processes and AppDomains

0

不要讓你的控制器MBR。創建一個小代理,將代理加載到第二個域中並啓動它。這樣控制器DLL將不會被加載到第一個域中。

+0

嗨陽光, 這是在一個共同的dll中使用IController接口背後的想法。 Controller.dll不會被加載到默認域中。控制器域中的Controller類的COM互操作似乎會導致COM相關的DLL被加載到默認域中。 – Xiaofu 2008-10-30 03:33:34

+0

更新:使用代理創建並在其他域中運行Controller具有相同的效果。 Controller.dll沒有被加載到默認的AppDomain中(這不是問題),但是COM interop的東西似乎仍然會將COM程序集加載回默認域中。 – Xiaofu 2008-10-30 03:34:20

2

這裏的證明,肖恩·威爾遜的答案是正確

Com App Domain

相關問題