Перечислить все AppDomains без mscoree
Как перечислить все домены процесса без ссылок 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();
}
}
1 ответов
не ссылаясь на 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, 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
}
}
пример использования:
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