Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does COM interop respect .NET AppDomain boundaries for assembly loading?

Here's the core problem: I have a .NET application that is using COM interop in a separate AppDomain. The COM stuff seems to be loading assemblies back into the default domain, rather than the AppDomain from which the COM stuff is being called.

What I want to know is: is this expected behaviour, or am I doing something wrong to cause these COM related assemblies to be loaded in the wrong AppDomain? Please see a more detailed description of the situation below...

The application consists of 3 assemblies: - the main EXE, the entry point of the application. - common.dll, containing just an interface IController (in the IPlugin style) - controller.dll, containing a Controller class that implements IController and MarshalByRefObject. This class does all the work and uses COM interop to interact with another application.

The relevant part of the main EXE looks like this:

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

The common.dll only contains these 2 things:

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

And the controller.dll contains this class (which also calls the COM interop stuff):

public class Controller: IController, MarshalByRefObject

When first running the application, Assembly.GetAssemblies() looks as expected, with common.dll being loaded in both AppDomains, and controller.dll only being loaded into the controller domain. After calling c.Run() however I see that assemblies related to the COM interop stuff have been loaded into the default AppDomain, and NOT in the AppDomain from which the COM interop is taking place.

Why might this be occurring?

And if you're interested, here's a bit of background:

Originally this was a 1 AppDomain application. The COM stuff it interfaces with is a server API which is not stable over long periods of use. When a COMException (with no useful diagnostic information as to its cause) occurs from the COM stuff, the entire application has to restarted before the COM connection will work again. Simply reconnecting to the COM app server results in immediate COM exceptions again. To cope with this I have tried to move the COM interop stuff into a seperate AppDomain so that when the mystery COMExceptions occur I can unload the AppDomain in which it occurs, create a new one and start again, all without having to manually restart the application. That was the theory anyway...

like image 453
Xiaofu Avatar asked Oct 28 '08 06:10

Xiaofu


People also ask

When assembly will load on AppDomain?

If an assembly is loaded into the same AppDomain, then the class can be instantiated in the usual way. But if an assembly is loaded into a different AppDomain then it can be instantiated using reflection. Another way is an interface.

What is the use of AppDomain in c#?

The AppDomain class implements a set of events that enable applications to respond when an assembly is loaded, when an application domain will be unloaded, or when an unhandled exception is thrown.

What is AppDomain used for?

An application domain (commonly called AppDomains) is a logical unit of isolation that enables you to execute multiple applications within the same process while at the same time ensuring that crash of a particular application domain doesn't affect the functioning of another application domain.

How many application domain can be used in single process?

Process A runs managed code with one application domain while Process B runs managed code has three application domains. Note that Process C which runs unmanaged code has no application domain.


2 Answers

Unfortunately, A COM component is loaded within Process Space and not within the context of an AppDomain. Thus, you will need to manually tear-down (Release and Unload) your Native DLLs (applies to both COM and P/Invoke). Simply destroying an appdomain will do you no good, but respawning the whole process shouldn't be necessary to reset COM state (simply recreating the COM object(s) should also normally work, this sounds like a bug within the component providers code, perhaps they can address it?)

References

(TechNet) Process Address Space

(MSDN) Application Domains

(MSDN) Boundaries: Processes and AppDomains

like image 193
Shaun Wilson Avatar answered Oct 19 '22 14:10

Shaun Wilson


Here's the proof that Shaun Wilson's answer is correct

Com App Domain

like image 21
Jeffrey Knight Avatar answered Oct 19 '22 12:10

Jeffrey Knight