Executing Code in Another AppDomain
The easiest way to run code in another appdomain is to execute an assembly entrypoint using AppDomain.ExecuteAssembly() or (starting in v2.0) AppDomain.ExecuteAssemblyByName().
If you want to execute a method other than an assembly entrypoint, call AppDomain.CreateInstance() on a type which extends MarshalByRefObject. Then, call a method on that type which does the Assembly.Load() or whatever work you needed to do there.
An easy way to get that to work is to have your MarshalByRefObject type be in your process exe. Then, call AppDomain.CreateInstanceFrom(Assembly.GetExecutingAssembly().Location, MBROtypeName).
Be sure to not pass any Type/Assembly/etc. instances (besides your MarshalByRefObject type) back to the original appdomain. If you do, it will cause those assemblies to be loaded into the original appdomain. If the appdomain settings are different between the two appdomains, those assemblies may not be loadable there. Plus, even if they are successfully loaded, the assemblies will remain loaded and locked after the target appdomain is unloaded, even if the original appdomain never uses them.
If the reason why you need to pass it back is so that it can interact with some assembly B in that other appdomain, instead, you could pass B to the new appdomain and do all of B's work there instead of in the original one. For example, for some applications, it's best if the only work done in the default appdomain is creating the new one and calling CreateInstanceFrom() on it. So, the new appdomain will do all the real work for that application.
Comments
Anonymous
June 14, 2003
Hi, I am curious you mention version 1.2 of the framework. Are you talking about the whidbey release as I thought that was version 2 of the framework.Just curious. By the way good blog lots of useful information.Anonymous
June 15, 2003
Thanks! Yes, today, it's 1.2. We'll see what it ships as.Anonymous
July 11, 2003
The comment has been removedAnonymous
July 11, 2003
Glad to help, but your comment is making me nervous. :) Sounds like you've already thought about the risks of using another assembly version. But, I hope that you're only doing a redirect to a version that is officially 'compatible' with the original... If not, please read http://blogs.msdn.com/suzcook/archive/2003/05/30/57159.aspx since version redirects are similar to partial binds.Anonymous
July 21, 2003
Martin: Looks like it will be 2.0 instead of 1.2, now, so I updated my entry. :)Anonymous
August 05, 2003
Hi, is it possible to implement a simple plugin mechanism in which the parent EXE can host unknown, late bound assemblies in a secondary appdomain, provide callbacks to them (via a standard 'IPlugin' interface, and not load them in the host EXE app domain itself? If passing types back from a loaded AppDomain means they are implicitly loaded in the host AppDomain this doesn't sound feasable. I have tried something similar before and the loading issues resulted in abandoning the isolated appdomain model in favor of just loading via reflection. Thanks,KrisAnonymous
August 06, 2003
Eric Gunnerson's article here answered my question nicely. Thanks again.Krishttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp05162002.aspAnonymous
December 02, 2003
Hi Suzanne,When I do AppDomain.CreateInstanceFrom(Assembly.GetExecutingAssembly().Location, MBROtypeName)would it result in my current assembly loaded into the AppDomain? It might be an overkill if we only need one type. Do you think it might be better to create a "glue" assembly containing only the MBROtype for this purpose?Regards,regAnonymous
December 04, 2003
Yes, it would be loaded there. But, assemblies already loaded in the process like that won't be remapped when they're loaded into another AppDomain. If you put the type in its own assembly, you'd have to pay additional performance costs of mapping the new file. (Other costs like the time to create a new Assembly instance would be required whether you use a new assembly or the current one.) So, it sounds like you should leave it as-is, unless you have other reasons to have another assembly for it.Anonymous
January 06, 2004
Suzanne, I am trying to load assemblies in the different AppDomain from remote machine. Executable is running on the machine and assemblies are stored on a network machine(with full permissions) . If I try loading these remote assemblies in the same AppDomain (of the executable), everything works fine. But, if I tried to load them in different AppDomain, I get System.IO.FileNotFoundException.I tried to use example given in Eric Gunnerson's article. example works if my assemblies are on local machine. (I think its because example uses MarshalByRefObject (RemoteLoader) in the local executable. Example first creates new appdoamin and create instance of the RemoteLoader in the new domain and then RemoteLoder tried to load assemblies in it.I tried to set following AppDomainSetup setup = new AppDomainSetup();setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;setup.ShadowCopyFiles = "true";setup.ShadowCopyDirectories = functionDirectory; //remote systemIf I set application base to the remote system(function directory) then myCreateInstanceAndUnwrap fails as remoteloder is part of my local executable.remoteLoader = (RemoteLoader) appDomain.CreateInstanceAndUnwrap( "SuperGraph", "SuperGraphInterface.RemoteLoader");Please Help. What exactly I need to do/ what am I doing wrong?ThanksAnonymous
January 28, 2004
Always start debugging file loading issues by getting the Fusion log (see http://blogs.msdn.com/suzcook/archive/2003/05/29/57120.aspx ). In this case, I imagine the problem is because the assemblies are loaded by path in the successful appdomain, but loaded by display name in the failing one. That's a problem when that path does not match the ApplicationBase for that appdomain (because that means that that assembly is not available in the Load context, and your CreateInstance*() call only looks in the Load context).
If it's required to load it from that path, consider changing the ApplicationBase (to use the Load context), or using CreateInstanceFrom*() instead (to use the LoadFrom context). See http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx for more info.Anonymous
March 03, 2004
Hi! The only way that I've found to resolve the problems discussed in this thread is to hook the AssemblyResolve event and "manually" load the assembly using the correct path. Creating a separate AppDomain isn't necessary. In fact, it's pretty much a no-brainer. Hope that helps.Anonymous
March 08, 2004
The comment has been removedAnonymous
April 20, 2004
Suzanne, I'm trying to use the AppDomain.CreateInstanceFrom method but it returns MarshalByRefObject instead of my type. This happens only when my assembly is located outside of private path of the current domain. The executing assembly itself is loaded using Assembly.LoadFrom method. What could be the problem? Thanks.Anonymous
April 20, 2004
Sounds like the assembly failed to load in the current appdomain. It will need to be loadable by display name, in the Load context of the appdomain where the type is Unwrap()'d. (The LoadFrom() is executed in the target appdomain, not the calling one.) My suggestions for making that work are in the blog entry above.Anonymous
April 20, 2004
The comment has been removedAnonymous
April 20, 2004
You must mean the AssemblyResolve event. It's not automatically found because resolving to a LoadFrom context assembly would make the Load context order-dependent. The appdomain transition causes the caller of Load() to be deserialization in mscorlib.dll, which is in the Load context. See http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx for more info about the different binding contexts.Anonymous
April 20, 2004
I did really mean AssemblyResolve event, sorry my typo. Thanks a lot.Anonymous
May 05, 2004
Hi Suzanne. Very useful blog for people new to AppDomains (like myself). Is there any way to have COM-callable .NET assemblies load in a separate self-designated application domain? This would be useful for controlling assembly versioning when you don't have control of the host, like MMC for example. Two MMC snapins might rely on the same assembly, but require different versions. The versions can be kept separate on the file system, but need the snapins to be loaded in separate AppDomains because MMC is one big process.Anonymous
May 05, 2004
Hi Suzanne,
As you mentioned i am trying to load a Windows Form Assembly at run time to a seprate AppDomain.
I don't want that this Assembly to be loaded in the Caller Domain, so i used the method
CreateInstanceFromAndUnwrap instead of AppDomain.Load(..)
// I am passing the Control's parent through the constructor argument
Object[] args1 = new Object[] {this};
MyControl.MyControl Ctrl = (MyControl.MyControl) MyDomain.CreateInstanceFromAndUnwrap("D:TestMyControl.dll",MyControl.MyControl,
false,BindingFlags.Public,null,args1,null,null,null);
But when i do this i get an exception thrown "Constructor on type MyControl.MyControl not found.
If i try to use the CreateInstanceFromAndUnwrap using the two parameters just the assembly and type, the function
returns me the control object. But when i try to set the Parent of the control using the following
code
Ctrl.Parent = this;
then system throws an exception the message is
The type System.Windows.Forms.Form+ControlCollection in Assembly System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is not marked as serializable.
What am i doing any thing wrong in this both scenarios.
Or is it advisable to have a design where i can load my Windows Forms Assemblies in to a seprate
Domain and use, and later unload it.Anonymous
July 01, 2004
Hi Suzanne,
Thanks for the great information. I'm currently trying to use an AppDomain to isolate "3rd party" plugins from the host application. At present, I create a new AppDomain and load the 3rd party assembly into it, then starting using the appropriate items. What I want to do is detect if anything "blows up" in the foreign assembly, and if so then reload the AppDomain. However, when I get an exception thrown within a test assembly it's just propogated to the /default/ AppDomain's UnhandledExceptionEventHandler. Even worse is that the sender object is actually the default AppDomain, not that where the exception occurred. Can you shed any light on this one?Anonymous
July 12, 2004
Hello Suzanne / all,
I am trying to load an assembly in a new AppDomain (so that I can unload the appdomain later on when it is not needed). I just wanted to know whether there is any performance hit in using AppDomain.CreateInstanceFrom method vs the AppDomain.CreateInstance method? My hunch is that CreateInstanceFrom would be faster when loading a "new" assembly in an appdomain since it does not have to search for the "new" assembly file..any comments?
vinayAnonymous
June 22, 2005
I tried to use another AppDomain to avoid the Memory Leak problem with XSLTs containing script code. Temporary assemblies are loaded in the main domain, noway to unload them!
string assemblyName = "MemoryLeak.Transform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=a738acded1cb795c";
string type = "MemoryLeak2.Transform.Class1";
System.Runtime.Remoting.ObjectHandle o = d.CreateInstance(assemblyName, type);
MemoryLeak2.Transform.Class1 c = (MemoryLeak2.Transform.Class1)o.Unwrap();
// do the transform
c.transform(stylesheet, filename);
AppDomain.Unload(d);
but assemblies like:
janzrica, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
qpeiskba, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
ncgptwtq, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
grow in the main appdomain!
Why?Anonymous
June 22, 2005
I noticed that in the constructor of the Created class the AppDomain is the 2nd, while I can't manage to invoke a function with 2 parameters without falling back to the main AppDomain. I also tried this:
object res1 =
(o.GetType()).InvokeMember(
"transform",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.InvokeMethod ,
null,
o,
new object [] {stylesheet, filename});
But the "transform" function gets executed in the main one.
How to do the trick???Anonymous
September 09, 2005
This whole system seems very awkward and cumbersome to me. Is anyone actually succeeding in creating plugin systems with runtime reloading?
I'm trying to load plugin assemblies into an AppDomain. Problem is that objects instantiated from these plugin assemblies generate events which the main program listens to.
So basically I really need to have real objects on the main-application side.
Is there not a simple solution to this VERY common need?Anonymous
November 07, 2005
Hi Suzanne. Very useful blog for people new to AppDomains (like myself). Is there any way to have COM-callable .NET assemblies load in a separated d d self-designated application domain? This would be useful for controlling assembly versioning when you don't have control of the host, like MMC for example. Two MMC snapins might rely on the same assembly, but require different versions. The versions can be kept separate on the file system, but need the snapins to be loaded in separate AppDomains because MMC is one big process.Anonymous
November 08, 2005
HI
can You give a simple code snippet suppoting your idea of communication between two appdomains?
This will be of great help
Thanks
Amol WankhedeAnonymous
July 18, 2006
As Mattia, I tried to use ExecuteAssembly to avoid the memory leak in compilation of XSLTs with scripts, as suggested in article 316775.
I have a service process repeatedly creating an AppDomain and calling ExecuteAssembly every 30 s, and I noticed another memory consumption.
I modified the code of the executed assembly to immediatly return, but I loose each time 16, 28 or 40 octets.
If I just comment out the ExecuteAssembly call, the memory leak disappear.
Seems that this AppDomain technology not so robust ...Anonymous
August 25, 2006
Hi Suzanne,
Like alot of people I've being having problems with this, AppDomain.CreateInstanceFromAndWrap.
I've posted on msdn forums http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=660892&SiteID=1
he post title is "Why does AppDomain.CreateInstanceAndUnwrap(..) work and AppDomain.CreateInstanceFrom(...).UnWrap doesn't? "
In there you'll see my problem.
Now I've forced the AppDomain appBasePath like so, to the location of my assembly and it's depenencies which I've grouped into this one dir:
AppDomain ad = AppDomain.CreateDomain("Compiling Gravity", null, "file:///C://myproj//Metadata", "file://C://myproj//Metadata", false);
Now when I try to invoke the function on the remote object using
Configuration.CompileProxy.Compiler compiler = (Configuration.CompileProxy.Compiler)(ad.CreateInstanceFromAndUnwrap("file:///C:\myproj\Metadata" + "\Configuration.CompileProxy.dll", "Configuration.CompileProxy.Compiler"));
I get the error
"Error: Unable to cast transparent proxy to type 'Configuration.CompileProxy.Compiler"
Any idea what's happening?
As I mentioned in the msdn forum post it all works fine if I put the same assembly into the GAC and create the AppDomain using CreateInstanceAndUnwrap("Configuration.CompileProxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1f77dad97b7dc0c2", "Configuration.CompileProxy.Compiler");Anonymous
October 11, 2006
La réflection est un des gros points forts de .Net. D'autant plus qu'il est très facile de s'en servir....Anonymous
March 21, 2007
There's no way to unload an individual assembly without unloading all of the appdomains containing it.Anonymous
April 12, 2007
I hesitate to talk about this because I don't want people who don't know about it to think, "Hey, what'sAnonymous
April 12, 2007
So, after checking out the binding context options , you've decided to switch your app to use the LoadAnonymous
April 18, 2007
The comment has been removedAnonymous
April 18, 2007
BTW, can you call a static class method through a marshaled/proxied (remoted) type? If so, how? Thanks!Anonymous
April 20, 2007
The comment has been removedAnonymous
May 10, 2007
The comment has been removedAnonymous
May 16, 2007
The comment has been removedAnonymous
May 30, 2007
Hi - to answer (Executing Code in Another AppDomain ) i found this option: Use something like this: string rutaFisicaEnsamblado = typeof (MyClass).Assembly.Location; int length= rutaFisicaEnsamblado.IndexOf("MyAssembly.dll"); rutaFisicaEnsamblado = rutaFisicaEnsamblado.Substring(0, length); and give that path to your AppDomain's ApplicationBase and PrivateBinPath Vuola!! And now i got some other issue i'm trying to solve: it marks the famous "Unable to cast transparent proxy to type" even the class myClass is implementing an IClass and it extends MarshallByRefObject... so, if not your issue I think you got it. RegardsAnonymous
June 04, 2008
Thanks for this posting. I had left out the MarshalByRef and was debugging why my cross-appdomain objects were executing the calling domain and not the new domain I had created them on... and this fixed it!Anonymous
November 04, 2008
I'm getting the FileNotFoundException or the SerializationExceptions when I attempt to register the ResolveEventHandler of my MarshalByRefObject derived class. myNewAppDomain.AssemblyResolve += myAssemblyResolver.Resolve; // throws FileNotFoundException and complains that the assembly's fullname cannot be found. I kinda get it - since I haven't added the handler to resolve assemblies, and I'm sending it the myAssemblyResolver which must be deserialized before use in the other app domain, how is the other app domain going to know how to deserialize it if I haven't been able to register the handler?? But of course, that's ALWAYS the case. The new app domain is /empty/ until you tell it to run some code, and in order to tell it that, you have to send it something it doesn't already know!! I've tried putting the MyAssemblyResolver type in the executing assembly, and I've tried putting it in a referenced assembly. Same basic error either way. And I had something similar working just last week without any problems.... It's got to be something stupid but I've been staring at it for hours and hours now.Anonymous
November 26, 2009
I have been searching all over for a solution to my app domain problems! And although your blog seems to have a few entries in it that are along the lines of what I'm doing, they don't exactly match. I'm hoping you could send me in the right direction! Basically..I have an updater program (say, UpdateService) that will be called, a sort of tool. When I have finished a new version of code for some software I am building, UpdateService will be run, and the user will choose the directory that the new software version is located at. UpdateService will then need to manually go through the whole folder, getting all dll's, loading them into a temp app domain, to get to the culture of each one, and then unload them when finished. Basically so that once the UpdateService has run, it will have an object fully populated with all locations of the files, along with certain details like culture if appropriate. I can't seem to get any of the dll's loaded into this temp app domain. Always advising me file load exception, or could not find file or one of its dependencies. All the dll's will be at a location anywhere on a computer, so they will not be in the app base for the UpdateService program. The folder that holds the software release, will not be in the same directory or appbase as the UpdateService program. Any ideas?