无需枚举所有mscoree的AppDomain [英] Enumerate all AppDomains without mscoree

查看:231
本文介绍了无需枚举所有mscoree的AppDomain的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何枚举所有进程的域不引用 mscoree 。是否可以?我发现从2007年某处在互联网的一些解决方案。但它枚举和空集



下面的代码:

 公共静态类DomainHelper 
{
公共静态的AppDomain [] loadedDomains
{
得到
{
变种loadedDomains =新的List<的AppDomain>();
变种runtimeHost =新CorRuntimeHost()作为ICorRuntimeHost;


{
VAR枚举= IntPtr.Zero;
runtimeHost.EnumDomains(出枚举);


{
对象nextDomain = NULL;
runtimeHost.NextDomain(枚举,楼盘nextDomain);

,而(nextDomain!= NULL)
{
loadedDomains.Add((应用程序域)nextDomain);
nextDomain = NULL;
runtimeHost.NextDomain(枚举,楼盘nextDomain);
}
}
终于
{
runtimeHost.CloseEnum(枚举);
}
}
终于
{
对Marshal.ReleaseComObject(runtimeHost);
}

返回loadedDomains.ToArray();
}
}

[ComImport]
[的Guid(CB2F6723-AB3A-11d2-9C40-00C04FA30A3E)]
类的私有CorRuntimeHost // :ICorRuntimeHost
{}

[的Guid(CB2F6722-AB3A-11D2-9C40-00C04FA30A3E)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
专用接口ICorRuntimeHost
{
无效CloseEnum(IntPtr的enumHandle);
无效则createdomain();
无效CreateDomainEx();
无效CreateDomainSetup();
无效CreateEvidence();
无效CreateLogicalThreadState();
无效CurrentDomain();
无效DeleteLogicalThreadState();
无效EnumDomains(出的IntPtr enumHandle);
无效GetConfiguration();
无效GetDefaultDomain();
无效LocksHeldByLogicalThread();
无效映射文件();
无效NextDomain(IntPtr的enumHandle,[的MarshalAs(UnmanagedType.IUnknown)Ref对象的AppDomain);
无效的start();
无效停止();
无效SwitchInLogicalThreadState();
无效SwitchOutLogicalThreadState();
无效UnloadDomain();
}
}


解决方案

不引用mscoree.tlb是越来越你陷入困境时,ICorRuntimeHost声明是错误的。该方法顺序完全混在一起,不清楚如何发生的。生活也简单得多早在2007年,托管界面彻底重新设计了.NET 4.0和ICorRuntimeHost已经过时了。它仍然有效,虽然,肯定一会儿就来了。



我会后,关于.NET 4.0和更高版本上运行的代码。正确的做法是先从ICLRMetaHost。然后获得你所感兴趣的运行实例的ICLRRuntimeInfo实例。请记住,.NET 4.0支持在进程并排侧CLR的实例化,你要发现你的代码是使用的人。 。然后ICLRRuntimeInfo :: GetInterface()方法可以返回一个实例到遗留ICorRuntimeHost接口

 使用系统; 
使用System.Collections.Generic;使用System.Runtime.InteropServices
;

公共静态类CLRUtil {
公共静态的IEnumerable< _AppDomain> EnumAppDomains(){
//获取ICLRMetaHost接口
对象objHost;
INT HR = CLRCreateInstance(REF CLSID_CLRMetaHost,裁判IID_CLRMetaHost,出objHost);
如果(HR℃下)抛出新收到COMException(无法创建元主机,小时);
VAR主机=(ICLRMetaHost)objHost;

//获取ICLRRuntimeInfo接口
VAR VERS = Environment.Version;
VAR versString =的String.Format(V {0} {1} {2}。vers.Major,vers.Minor,vers.Build);
VAR objRuntime = host.GetRuntime(versString,楼盘IID_CLRRuntimeInfo);
变种运行时间=(ICLRRuntimeInfo)objRuntime;
BOOL启动;
UINT标志;
runtime.IsStarted(出开始,出旗);
如果(开始!)抛出新收到COMException(CLR不启动?);

//获取传统ICorRuntimeHost接口和迭代的AppDomain
VAR V2Host =(ICorRuntimeHost)runtime.GetInterface(REF CLSID_CorRuntimeHost,裁判IID_CorRuntimeHost);
IntPtr的hDomainEnum;
V2Host.EnumDomains(出hDomainEnum);
为(;;){
_AppDomain域= NULL;
V2Host.NextDomain(hDomainEnum,出域);
如果(域== NULL)破;
收益率的回报域;
}
V2Host.CloseEnum(hDomainEnum);
}

私有静态的Guid = CLSID_CLRMetaHost新的GUID(0x9280188d,0xe8e,0x4867,0xb3,位于0xC,0x7f中,0xa8,0x38,的0x84,0xe8,写0x​​DE);
私有静态的Guid = IID_CLRMetaHost新的GUID(0xD332DB9E,0xB9B3,0x4125,为0x82,0x07执行,0xA1,0x48,的0x84,0xF5,0x32,0x16);
私有静态的Guid = IID_CLRRuntimeInfo新的GUID(0xBD39D1D2,0xBA2F,0x486a,0x89上,反0xB0,0xB4,反0xB0,0xCB,0×46,为0x68,0x91的信息);
私有静态的Guid = CLSID_CorRuntimeHost新的GUID(0xcb2f6723,0xab3a,0x11d2,为0x9c,0X40,为0x00,将0xC0,0x4f,0xA3执行,0x0A的,0x3E的);
私有静态的Guid = IID_CorRuntimeHost新的GUID(0xcb2f6722,0xab3a,0x11d2,为0x9c,0X40,为0x00,将0xC0,0x4f,0xA3执行,0x0A的,0x3E的);

函数[DllImport(mscoree.dll中)]
私人静态外部INT CLRCreateInstance(REF的Guid CLSID,裁判的Guid IID,
[的MarshalAs(UnmanagedType.Interface)] out对象PTR);

[ComImport,与GUID(D332DB9E-B9B3-4125-8207-A14884F53216),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
专用接口ICLRMetaHost {
[返回:的MarshalAs( UnmanagedType.Interface)]
对象GetRuntime(字符串版本,裁判的Guid IID);
//休息省略
}

[ComImport,与GUID(BD39D1D2-BA2F-486A-89B0-B4B0CB466891),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
专用接口ICLRRuntimeInfo {
无效GetVersionString(的char []缓冲区,INT BufferLength中);
无效GetRuntimeDirectory(的char []缓冲区,INT BufferLength中);
布尔IsLoaded(IntPtr的hProcess);
无效LoadErrorString(UINT ID,CHAR []缓冲区,INT BufferLength中,诠释LCID);
无效调用LoadLibrary(字符串路径,出的IntPtr hMdodule);
无效GetProcAddress函数(字符串名称,出的IntPtr地址);
[返回:的MarshalAs(UnmanagedType.Interface)
对象GetInterface(REF的Guid CLSID,裁判的Guid IID);
布尔IsLoadable();
无效SetDefaultStartupFlags(UINT旗,串CONFIGFILE);
无效GetDefaultStartupFlags(UINT出旗,CHAR [] CONFIGFILE,INT configFileLength);
无效BindAsLegacyV2Runtime();
无效IsStarted(OUT BOOL开始,出旗UINT);
}

[ComImport,与GUID(CB2F6722-AB3A-11d2-9C40-00C04FA30A3E),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
专用接口ICorRuntimeHost {
无效CreateLogicalThreadState();
无效DeleteLogicalThreadState();
无效SwitchinLogicalThreadState(IntPtr的饼干);
无效SwitchoutLogicalThreadState(出IntPtr的饼干);
无效LocksHeldByLogicalThread(OUT INT计数);
无效映射文件(IntPtr的HFILE,出的IntPtr地址);
无效GetConfiguration(出IntPtr的配置);
无效的start();
无效停止();
无效则createdomain(字符串名称,对象标识,出_AppDomain域);
无效GetDefaultDomain(出_AppDomain域);
无效EnumDomains(出的IntPtr hEnum);
无效NextDomain(IntPtr的hEnum,出_AppDomain域);
无效CloseEnum(IntPtr的hEnum);
//休息省略
}
}



使用示例:

 类节目{
静态无效的主要(字串[] args){
AppDomain.CreateDomain(例);
的foreach(在CLRUtil.EnumAppDomains VAR域()){
Console.WriteLine(找到的AppDomain {0},domain.FriendlyName);
}
到Console.ReadLine();
}
}



输出:

 找到的AppDomain ConsoleApplication1.vshost.exe 
发现的AppDomain实例


How to enumerate all the process' domains without referencing mscoree. Is it possible? I found some solution from 2007 year somewhere in the Internet. But it enumerates and empty collection.

Here's the code:

public static class DomainHelper
{
    public static AppDomain[] LoadedDomains
    {
        get
        {
            var loadedDomains = new List<AppDomain>();
            var runtimeHost = new CorRuntimeHost() as ICorRuntimeHost;

            try
            {
                var 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 CloseEnum(IntPtr enumHandle);
        void CreateDomain();
        void CreateDomainEx();
        void CreateDomainSetup();
        void CreateEvidence();
        void CreateLogicalThreadState();
        void CurrentDomain();
        void DeleteLogicalThreadState();
        void EnumDomains(out IntPtr enumHandle);
        void GetConfiguration();
        void GetDefaultDomain();
        void LocksHeldByLogicalThread();
        void MapFile();
        void NextDomain(IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)] ref object appDomain);
        void Start();
        void Stop();
        void SwitchInLogicalThreadState();
        void SwitchOutLogicalThreadState();
        void UnloadDomain();
    }
}

解决方案

Not referencing mscoree.tlb is what is getting you into trouble, the ICorRuntimeHost is declared wrong. The method order is completely mixed up, unclear how that happened. Life was also much simpler back in 2007, the hosting interface was drastically redesigned for .NET 4.0 and ICorRuntimeHost is deprecated. It still works though, surely for a while to come.

I'll post code that runs on .NET 4.0 and higher. Proper approach is to start with ICLRMetaHost. Then obtain the ICLRRuntimeInfo instance for the runtime instance that you are interested in. Keep in mind that .NET 4.0 supports in-process side-by-side instancing of the CLR, you'll want to find the one that your code is using. The ICLRRuntimeInfo::GetInterface() method can then return an instance to the legacy ICorRuntimeHost interface.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public static class CLRUtil {
    public static IEnumerable<_AppDomain> EnumAppDomains() {
        // Obtain ICLRMetaHost interface
        object objHost;
        int hr = CLRCreateInstance(ref CLSID_CLRMetaHost, ref IID_CLRMetaHost, out objHost);
        if (hr < 0) throw new COMException("Cannot create meta host", hr);
        var host = (ICLRMetaHost)objHost;

        // Obtain ICLRRuntimeInfo interface
        var vers = Environment.Version;
        var versString = string.Format("v{0}.{1}.{2}", vers.Major, vers.Minor, vers.Build);
        var objRuntime = host.GetRuntime(versString, ref IID_CLRRuntimeInfo);
        var runtime = (ICLRRuntimeInfo)objRuntime;
        bool started;
        uint flags;
        runtime.IsStarted(out started, out flags);
        if (!started) throw new COMException("CLR not started??");

        // Obtain legacy ICorRuntimeHost interface and iterate appdomains
        var V2Host = (ICorRuntimeHost)runtime.GetInterface(ref CLSID_CorRuntimeHost, ref IID_CorRuntimeHost);
        IntPtr hDomainEnum;
        V2Host.EnumDomains(out hDomainEnum);
        for (;;) {
            _AppDomain domain = null;
            V2Host.NextDomain(hDomainEnum, out domain);
            if (domain == null) break;
            yield return domain;
        }
        V2Host.CloseEnum(hDomainEnum);
    }

    private static Guid CLSID_CLRMetaHost = new Guid(0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde);
    private static Guid IID_CLRMetaHost = new Guid(0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);
    private static Guid IID_CLRRuntimeInfo = new Guid(0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);
    private static Guid CLSID_CorRuntimeHost = new Guid(0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
    private static Guid IID_CorRuntimeHost = new Guid(0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);

    [DllImport("mscoree.dll")]
    private static extern int CLRCreateInstance(ref Guid clsid, ref Guid iid,
        [MarshalAs(UnmanagedType.Interface)] out object ptr);

    [ComImport, Guid("D332DB9E-B9B3-4125-8207-A14884F53216"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface ICLRMetaHost {
        [return: MarshalAs(UnmanagedType.Interface)]
        object GetRuntime(string version, ref Guid iid);
        // Rest omitted
    }

    [ComImport, Guid("BD39D1D2-BA2F-486a-89B0-B4B0CB466891"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface ICLRRuntimeInfo {
        void GetVersionString(char[] buffer, int bufferLength);
        void GetRuntimeDirectory(char[] buffer, int bufferLength);
        bool IsLoaded(IntPtr hProcess);
        void LoadErrorString(uint id, char[] buffer, int bufferLength, int lcid);
        void LoadLibrary(string path, out IntPtr hMdodule);
        void GetProcAddress(string name, out IntPtr addr);
        [return: MarshalAs(UnmanagedType.Interface)]
        object GetInterface(ref Guid clsid, ref Guid iid);
        bool IsLoadable();
        void SetDefaultStartupFlags(uint flags, string configFile);
        void GetDefaultStartupFlags(out uint flags, char[] configFile, int configFileLength);
        void BindAsLegacyV2Runtime();
        void IsStarted(out bool started, out uint flags);
    }

    [ComImport, Guid("CB2F6722-AB3A-11d2-9C40-00C04FA30A3E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface ICorRuntimeHost {
        void CreateLogicalThreadState();
        void DeleteLogicalThreadState();
        void SwitchinLogicalThreadState(IntPtr cookie);
        void SwitchoutLogicalThreadState(out IntPtr cookie);
        void LocksHeldByLogicalThread(out int count);
        void MapFile(IntPtr hFile, out IntPtr address);
        void GetConfiguration(out IntPtr config);
        void Start();
        void Stop();
        void CreateDomain(string name, object identity, out _AppDomain domain);
        void GetDefaultDomain(out _AppDomain domain);
        void EnumDomains(out IntPtr hEnum);
        void NextDomain(IntPtr hEnum, out _AppDomain domain);
        void CloseEnum(IntPtr hEnum);
        // rest omitted
    }
}

Sample usage:

class Program {
    static void Main(string[] args) {
        AppDomain.CreateDomain("Example");
        foreach (var domain in CLRUtil.EnumAppDomains()) {
            Console.WriteLine("Found appdomain {0}", domain.FriendlyName);
        }
        Console.ReadLine();
    }
}

Output:

Found appdomain ConsoleApplication1.vshost.exe
Found appdomain Example

这篇关于无需枚举所有mscoree的AppDomain的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆