About Me

I was born in Mobile, AL and graduated from Theodore High School in 1990. I received a BS in Pure Mathematics from the University of Alabama in 1995. I now reside in Hoover, AL.

Tuesday, October 9, 2007

Getting a list of loaded AppDomains

Oftentimes, I have a need to view the currently loaded appdomains in my application. An example of this is when I am creating a private application domain to load memory intensive objects that may be static or prone to memory leaks. The benefit of having these objects in a different appdomain than my code should be obvious: I can unload the private appdomain to cleanup my memory space. Now, I want to use this application domain throughout my application, from within the default application domains and any child domains. Creating a static reference to this private domain is insufficient, as statics are scoped to the application domain in which they are created. So what I need is a way to iterate through the application domains in my application and create the private application domain if it does not exists, or reference the private domain if it does exist.

When I first started development of this solution, I referenced mscoree for the ICorRuntimeHost interface and the CorRuntimeHost class, but as this added another dll to my deployment, I decided to hand-code the signatures for these objects in my code.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
 
/// <summary>
/// Provides a helper class for appdomains.
/// </summary>
public static class DomainHelper
{
   /// <summary>
   /// Gets all of the application domains that are 
   /// currently loaded in the application process.
   /// </summary>
   public static AppDomain[] LoadedDomains
   {
      get
      {
         List<AppDomain> loadedDomains = new List<AppDomain>();
         ICorRuntimeHost runtimeHost = (ICorRuntimeHost)(new CorRuntimeHost());
 
         try
         {
            IntPtr enumeration = IntPtr.Zero;
            runtimeHost.EnumDomains(out enumeration);
 
            try
            {
               object nextDomain = null;
               runtimeHost.NextDomain(enumeration, ref nextDomain);
 
               while (nextDomain != null)
               {
                  loadedDomains.Add((AppDomain)nextDomain);
                  nextDomain = null;
                  runtimeHost.NextDomain(enumeration, ref nextDomain);
               }
            }
            finally
            {
               runtimeHost.CloseEnum(enumeration);
            }
         }
         finally
         {
            Marshal.ReleaseComObject(runtimeHost);
         }
 
         return loadedDomains.ToArray();
      }
   }
 
   [ComImport]
   [Guid("CB2F6723-AB3A-11d2-9C40-00C04FA30A3E")]
   private class CorRuntimeHost// : ICorRuntimeHost
   {
   }
 
   [Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
   [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
   private interface ICorRuntimeHost
   {
      void CreateLogicalThreadState ();
      void DeleteLogicalThreadState ();
      void SwitchInLogicalThreadState ();
      void SwitchOutLogicalThreadState ();
      void LocksHeldByLogicalThread ();
      void MapFile ();
      void GetConfiguration ();
      void Start ();
      void Stop ();
      void CreateDomain ();
      void GetDefaultDomain ();
      void EnumDomains (out IntPtr enumHandle);
      void NextDomain (IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)]ref object appDomain);
      void CloseEnum (IntPtr enumHandle);
      void CreateDomainEx ();
      void CreateDomainSetup ();
      void CreateEvidence ();
      void UnloadDomain ();
      void CurrentDomain ();
   }
}

One point of interest here is that the definition of the ICorRuntimeHost interface contains parameterized definitions for only the methods of interest to the LoadedDomains property.

2 comments:

arc said...

Thank you a lot! I have implemented cross appdomain singleton without any mscoree attached dll for net 3.5 with help of your ideas. it works on 32 and 64 bit OSes now. Thanks.

Praveen T2 said...

Thanks a ton, This helped me to understand even while interop is being done not necessarily seperate appdomains are created.