C# 在进程中创建新appdomain时通知

C# 在进程中创建新appdomain时通知,c#,.net,C#,.net,考虑下一种情况。我已经使用EasyHook将托管dll注入到进程中。EasyHook使用单独的AppDomain注入dll。现在我需要一种方法来获取有关在当前进程中创建新AppDomain的通知。 因此,问题是,在创建新AppDomain的过程中,有没有一种方法可以获取通知?没有任何事件或简单的方法可以做到这一点,有一个COM中断允许您获取加载的应用程序域列表,但任何事件等都在专用接口上对我们隐藏 有两种方法可以做到这一点,但这两种方法都要求您积极寻求信息,即没有需要注册的事件 使用性能计数器

考虑下一种情况。我已经使用EasyHook将托管dll注入到进程中。EasyHook使用单独的AppDomain注入dll。现在我需要一种方法来获取有关在当前进程中创建新AppDomain的通知。
因此,问题是,在创建新AppDomain的过程中,有没有一种方法可以获取通知?

没有任何事件或简单的方法可以做到这一点,有一个COM中断允许您获取加载的应用程序域列表,但任何事件等都在专用接口上对我们隐藏

有两种方法可以做到这一点,但这两种方法都要求您积极寻求信息,即没有需要注册的事件

  • 使用性能计数器
  • 使用mscoreecom中断
  • 这两个选项可以相互补充,但这取决于您需要的信息级别

    使用性能计数器

    CLR有许多可用的性能计数器,但我们关心的计数器位于类别“.Net CLR Loading”中,它是名为“Total Appdomains”的计数器

    使用System.Diagnostics命名空间,您可以获得计算机中运行的每个实例/进程的应用程序域数

    如下面的代码所示:

    PerformanceCounter toPopulate = new PerformanceCounter(".Net CLR Loading", "Total Appdomains", "ConsoleApplication2.vshost", true);
    
    Console.WriteLine("App domains listed = {0}", toPopulate.NextValue().ToString());
    
    (请注意,如果您创建自己的应用程序,示例需要应用程序实例名称,请确保更改此名称)

    当数字改变时,你可以将其包装在一个循环中,并为你的应用程序提出一个偶数。 (不雅致,但目前无法绕过)

    使用mscoree COM中断

    此外,如果要列出进程中的所有应用程序域,则需要使用MSCOREE.TBL库,该库是CLR主机使用的COM库

    您可以在C:\WINDOWS\Microsoft.NET\Framework\VXXXXX\mscoree.tlb中找到该库 使用mscoree

    如果在窗口7或更高版本上使用它,则必须确保“引用属性”中的“嵌入程序集类型”已关闭,因为此程序集不能像那样嵌入。 请参阅有关此stack post的更多信息:

    请参阅下面的代码,了解如何返回和列出流程中的所有应用程序域(这将返回每个应用程序域的实际AppDomain实例)。 可在以下位置找到此操作的原始堆栈帖子:

    公共静态列表GetAppDomains()
    {
    列表_IList=新列表();
    IntPtr enumHandle=IntPtr.Zero;
    CorRuntimeHostClass host=new mscoree.CorRuntimeHostClass();
    尝试
    {
    host.EnumDomains(out-enumHandle);
    对象域=空;
    while(true)
    {
    host.NextDomain(enumHandle,out-domain);
    如果(域==null)中断;
    AppDomain AppDomain=(AppDomain)域;
    _IList.Add(appDomain);
    }
    返回IList;
    }
    捕获(例外e)
    {
    Console.WriteLine(如ToString());
    返回null;
    }
    最后
    {
    host.CloseEnum(enumHandle);
    Marshal.ReleaseComObject(主机);
    }
    }
    
    现在,您可以看到一个进程中存在多少应用程序域,并列出它们,让我们对其进行测试

    下面是一个使用这两种技术的完全有效的示例

    using System;
    using System.Collections.Generic;
    using System.Drawing.Printing;
    using System.Linq;
    using System.Printing;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    using System.Windows.Xps.Packaging;
    using System.Runtime.InteropServices;
    using mscoree;
    using System.Diagnostics;
    using System.Threading;                           
    
    namespace ConsoleApplication2
    {
        class AppDomainWorker
        {
            public void DoSomeWork()
            {
                while (true)
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        var hello = "hello world".GetHashCode();
                    }
                    Thread.Sleep(500);
                }
            }
        }
    
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                PerformanceCounter toPopulate = new PerformanceCounter(".Net CLR Loading", "Total Appdomains", "ConsoleApplication2.vshost", true);
    
                Console.WriteLine("App domains listed = {0}", toPopulate.NextValue().ToString());
    
                for (int i = 0; i < 10; i++)
                {
                    AppDomain domain = AppDomain.CreateDomain("App Domain " + i);
                    domain.DoCallBack(() => new Thread(new AppDomainWorker().DoSomeWork).Start());
    
                    Console.WriteLine("App domains listed = {0}", toPopulate.NextValue().ToString());
                }
    
                Console.WriteLine("List all app domains");
                GetAppDomains().ForEach(a => {
                    Console.WriteLine(a.FriendlyName);
                });
    
                Console.WriteLine("running, press any key to stop");
    
                Console.ReadKey();        
            }
    
            public static List<AppDomain> GetAppDomains()
            {
                List<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);
                }
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用系统、绘图、打印;
    使用System.Linq;
    使用系统。打印;
    使用系统文本;
    使用System.Threading.Tasks;
    使用System.Windows.Controls;
    使用System.Windows.Xps.Packaging;
    使用System.Runtime.InteropServices;
    使用mscoree;
    使用系统诊断;
    使用系统线程;
    命名空间控制台应用程序2
    {
    类AppDomainWorker
    {
    公共工程
    {
    while(true)
    {
    对于(int i=0;i<1000;i++)
    {
    var hello=“hello world.GetHashCode();
    }
    睡眠(500);
    }
    }
    }
    班级计划
    {
    [状态线程]
    静态void Main(字符串[]参数)
    {
    PerformanceCounter toPopulate=新的PerformanceCounter(“.Net CLR加载”、“Appdomains总数”、“ConsoleApplication2.vshost”,true);
    WriteLine(“列出的应用程序域={0}”,toPopulate.NextValue().ToString());
    对于(int i=0;i<10;i++)
    {
    AppDomain域=AppDomain.CreateDomain(“应用域”+i);
    domain.DoCallBack(()=>新线程(新AppDomainWorker().DoSomeWork.Start());
    WriteLine(“列出的应用程序域={0}”,toPopulate.NextValue().ToString());
    }
    Console.WriteLine(“列出所有应用程序域”);
    GetAppDomains().ForEach(a=>{
    Console.WriteLine(a.FriendlyName);
    });
    Console.WriteLine(“正在运行,按任意键停止”);
    Console.ReadKey();
    }
    公共静态列表GetAppDomains()
    {
    列表_IList=新列表();
    IntPtr enumHandle=IntPtr.Zero;
    CorRuntimeHostClass host=new mscoree.CorRuntimeHostClass();
    尝试
    {
    host.EnumDomains(out-enumHandle);
    对象域=空;
    while(true)
    {
    host.NextDomain(enumHandle,out-domain);
    如果(域==null)中断;
    AppDomain AppDomain=(AppDomain)域;
    _IList.Add(appDomain);
    }
    返回IList;
    }
    捕获(例外e)
    {
    Console.WriteLine(如ToString());
    返回null;
    }
    最后
    {
    host.CloseEnum(enumHandle);
    Marshal.ReleaseComObject(主机);
    }
    }
    }
    }
    

    我希望这会有帮助,如果您需要进一步的帮助,请告诉我们。

    您需要进一步的帮助吗?我选择了两个恶魔中的较小者。创建了一个定时器和peri
    using System;
    using System.Collections.Generic;
    using System.Drawing.Printing;
    using System.Linq;
    using System.Printing;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    using System.Windows.Xps.Packaging;
    using System.Runtime.InteropServices;
    using mscoree;
    using System.Diagnostics;
    using System.Threading;                           
    
    namespace ConsoleApplication2
    {
        class AppDomainWorker
        {
            public void DoSomeWork()
            {
                while (true)
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        var hello = "hello world".GetHashCode();
                    }
                    Thread.Sleep(500);
                }
            }
        }
    
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                PerformanceCounter toPopulate = new PerformanceCounter(".Net CLR Loading", "Total Appdomains", "ConsoleApplication2.vshost", true);
    
                Console.WriteLine("App domains listed = {0}", toPopulate.NextValue().ToString());
    
                for (int i = 0; i < 10; i++)
                {
                    AppDomain domain = AppDomain.CreateDomain("App Domain " + i);
                    domain.DoCallBack(() => new Thread(new AppDomainWorker().DoSomeWork).Start());
    
                    Console.WriteLine("App domains listed = {0}", toPopulate.NextValue().ToString());
                }
    
                Console.WriteLine("List all app domains");
                GetAppDomains().ForEach(a => {
                    Console.WriteLine(a.FriendlyName);
                });
    
                Console.WriteLine("running, press any key to stop");
    
                Console.ReadKey();        
            }
    
            public static List<AppDomain> GetAppDomains()
            {
                List<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);
                }
            }
        }
    }