List AppDomains in Process
Asked Answered
J

3

62

Is there any possibility how to enumerate AppDomains within Process?

Jaffe answered 23/12, 2008 at 10:9 Comment(0)
M
75

You may want to look at this post

using System.Runtime.InteropServices;
// Add the following as a COM reference - C:\WINDOWS\Microsoft.NET\Framework\vXXXXXX\mscoree.tlb
using mscoree;                              

        public static IList<AppDomain> GetAppDomains()
        {
            IList<AppDomain> _IList = new List<AppDomain>();
            IntPtr enumHandle = IntPtr.Zero
            CorRuntimeHostClass host = new mscoree.CorRuntimeHostClass();
            try
            {
                host.EnumDomains(out enumHandle);
                object domain = null;
                while (true)
                {
                    host.NextDomain(enumHandle, out domain);
                    if (domain == null) break;
                    AppDomain appDomain = (AppDomain)domain;
                    _IList.Add(appDomain);
                }
                return _IList;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return null;
            }
            finally
            {
                host.CloseEnum(enumHandle);
                Marshal.ReleaseComObject(host);
            }
        } 
    }
Markman answered 23/12, 2008 at 10:25 Comment(4)
In .NET 4.0, you have to replace CorRuntimeHostClass host = new CorRuntimeHostClass(); with ICorRuntimeHost host = new CorRuntimeHost();.Metralgia
I just want to say thankyou for this snippet of code. Very useful.Windstorm
See #2484159 if you want to use CorRuntimeHostClass instead of ICorRuntimeHost in .NET 4.0Ahmadahmar
For anyone like me who wasn't familiar with adding a COM reference, I was able to do this by right clicking the project, going to Add->Reference, and then checking COM->Common Language Runtime Execution EnvironmentBrewer
T
10

UPDATE

You can add the interface ICorRuntimeHost as:

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace mscoree
{
    [CompilerGenerated]
    [Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [TypeIdentifier]
    [ComImport]
    [CLSCompliant(false)]
    public interface ICorRuntimeHost
    {
        void _VtblGap1_11();

        void EnumDomains(out IntPtr enumHandle);

        void NextDomain([In] IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)] out object appDomain);

        void CloseEnum([In] IntPtr enumHandle);
    }
}

And add a method:

private static ICorRuntimeHost GetCorRuntimeHost()
{
    return (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}

Then you don't need the mscoree.tlb reference. And make some changes as:

using mscoree;
ICorRuntimeHost host = null;
host = GetCorRuntimeHost();

It's my current code for this problem.


Original answer

I refine it as this:

using System.Runtime.InteropServices;
using mscoree;

public static IEnumerable<AppDomain> EnumAppDomains()
{
    IntPtr enumHandle = IntPtr.Zero;
    CorRuntimeHostClass host = null;

    try
    {
        host = new CorRuntimeHostClass();
        host.EnumDomains(out enumHandle);
        object domain = null;

        host.NextDomain(enumHandle, out domain);
        while (domain != null)
        {
            yield return (AppDomain)domain;
            host.NextDomain(enumHandle, out domain);
        }
    }
    finally
    {
        if (host != null)
        {
            if (enumHandle != IntPtr.Zero)
            {
                host.CloseEnum(enumHandle);
            }

            Marshal.ReleaseComObject(host);
        }
    }
}

Call it as this:

foreach (AppDomain appDomain in EnumAppDomains())
{
    // use appDomain
}

Remember to reference COM object \WINDOWS\Microsoft.NET\Framework\vXXX\mscoree.tlb, set reference mscoree "Embed Interop Types" as "False".

Teacher answered 19/2, 2014 at 3:51 Comment(3)
this tells me "ICorRuntimeHost is inaccessible because of it's protection level".Donaugh
Thanks for your question. The original post should use CorRuntimeHostClass instead of `ICorRuntimeHost'. I have another better way provided as an update to the original answer.Teacher
This worked for me, where we wanted to open html page as part of outlook addin.Gay
O
0

VB.NET:

<System.Runtime.CompilerServices.CompilerGenerated>
<System.Runtime.InteropServices.Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")>
<System.Runtime.InteropServices.InterfaceType(Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)>
<System.Runtime.InteropServices.ComImport>
<System.CLSCompliant(False)>
Interface ICorRuntimeHost
    Sub _VtblGap1_11()
    Sub EnumDomains(<System.Runtime.InteropServices.Out> ByRef enumHandle As IntPtr)
    Sub NextDomain(<System.Runtime.InteropServices.[In]> ByVal enumHandle As IntPtr, <System.Runtime.InteropServices.Out> <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IUnknown)> ByRef appDomain As Object)
    Sub CloseEnum(<System.Runtime.InteropServices.[In]> ByVal enumHandle As IntPtr)
End Interface

Private Function GetCorRuntimeHost() As ICorRuntimeHost
    Return CType(Activator.CreateInstance(System.Type.GetTypeFromCLSID(New Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E"))), ICorRuntimeHost)
End Function

Public Function GetAppDomains() As List(Of AppDomain)
    Dim ls As List(Of AppDomain) = New List(Of AppDomain)
    Dim enumHandle As IntPtr = IntPtr.Zero

    Dim host As ICorRuntimeHost = GetCorRuntimeHost()

    Try
        host.EnumDomains(enumHandle)
        Dim domain As Object = Nothing

        While True
            host.NextDomain(enumHandle, domain)
            If domain Is Nothing Then Exit While
            Dim appDomain As AppDomain = CType(domain, AppDomain)
            ls.Add(appDomain)
        End While

        Return ls
    Catch e As Exception
        Console.WriteLine(e.ToString())
        Return Nothing
    Finally
        host.CloseEnum(enumHandle)
        Runtime.InteropServices.Marshal.ReleaseComObject(host)
    End Try
End Function

Usage:

Dim ls As List(Of AppDomain) = GetAppDomains()
System.Console.WriteLine(ls)
Operative answered 27/5, 2020 at 7:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.