如何在不引用mscoree的情况下枚举所有进程的域.可能吗?我从互联网上的某个地方找到了2007年的解决方案.但它列举并清空收集.
这是代码:
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(); } }
解决方法
不引用mscoree.tlb会让你遇到麻烦,ICorRuntimeHost声明错误.方法顺序完全混淆,不清楚是怎么回事. 2007年,生活也变得更加简单,主机界面针对.NET 4.0进行了彻底重新设计,并且不推荐使用ICorRuntimeHost.它仍然有效,肯定会有一段时间.
我将发布在.NET 4.0及更高版本上运行的代码.正确的方法是从ICLRMetaHost开始.然后获取您感兴趣的运行时实例的ICLRRuntimeInfo实例.请记住,.NET 4.0支持CLR的进程内并行实例化,您将需要找到您的代码正在使用的实例.然后,ICLRRuntimeInfo :: GetInterface()方法可以将实例返回到传统的ICorRuntimeHost接口.
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,0xF5,0x32,0x16); private static Guid IID_CLRRuntimeInfo = new Guid(0xBD39D1D2,0xBA2F,0x486a,0x89,0xB0,0xB4,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,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 } }
样品用法:
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(); } }
输出:
Found appdomain ConsoleApplication1.vshost.exe Found appdomain Example