C# 跨appDomain访问Console.Out

C# 跨appDomain访问Console.Out,c#,appdomain,C#,Appdomain,我需要读取应用程序(Core.exe)的标准输出,该应用程序在同一进程中运行,但在不同的appDomain中运行。处理进程时,重定向输出非常容易,但appDomains的概念对我来说是新概念 所以。。我在隔离的appDomain中这样启动应用程序 new HostedApp("core", "Core.exe").Run(); class HostedApp { internal string DomainName; internal string AssemblyName;

我需要读取应用程序(Core.exe)的标准输出,该应用程序在同一进程中运行,但在不同的appDomain中运行。处理进程时,重定向输出非常容易,但appDomains的概念对我来说是新概念

所以。。我在隔离的appDomain中这样启动应用程序

new HostedApp("core", "Core.exe").Run();

class HostedApp
{
    internal string DomainName;
    internal string AssemblyName;
    internal AppDomain Ad;
    internal Thread AppThrd;

    public HostedApp(string a_domain, string a_assemblyName)
    {
        DomainName = a_domain;
        AssemblyName = a_assemblyName;
        Ad = AppDomain.CreateDomain(a_domain);
    }

    public void Run()
    {
        AppThrd = new Thread(RunApp);
        AppThrd.Start();
    }

    private void RunApp()
    {
        try
        {
            Ad.ExecuteAssembly(AssemblyName);
        }
        catch(Exception _ex)
        {
            MessageBox.Show("Unhandled exception\n" + _ex);
        }
    }
}
我已经尝试重定向控制台。在当前进程之外,假设如果应用程序共享同一进程,则将有单个standart输出

但它只显示默认的appDomain标准输出

因此,总而言之,我需要访问另一个appDomain应用程序standart输出。或者可能有一种方法可以从“核心”appDomain调用默认appDomain中的方法?

也许这可以帮助您。 我使用这些类来监听远程AppDomains跟踪(Write/WriteLine)调用

第一个类允许我将TraceListen Write/WriteLine方法重定向到自定义委托


公共委托无效TraceWriterHandler(字符串消息);
内部类SynchronizedTraceListener:TraceListener
{
私有TraceWriterHandler messageHandler;
公共同步TraceListener(TraceWriterHandler writeHandler)
{
messageHandler=writeHandler;
}
公共重写无效写入(字符串消息)
{
messageHandler(message);
}
公共覆盖无效写线(字符串消息)
{
messageHandler(message+System.Environment.NewLine);
}
}
然后是我的远程AppDomain跟踪侦听器类的核心。 这是棘手的部分。我尽量不把解释搞砸。这对我来说是个棘手的问题,但事情是这样的

  • (本地)CrossDomainTracer对象在远AppDomain上创建(远)CrossDomainTracer对象
  • (本地)CrossDomainRacer对象调用(远)CrossDomainRacer对象。StartListening并将其自身作为引用发送(本地)
  • (far)CrossDomainTracer对象开始侦听(far)域中的任何Trace.Write/WriteLine调用
  • 进行(远)Trace.Write/WriteLine调用时,它会从(本地)远程AppDomain调用.RemoteWrite方法
  • (本地).RemoteWrite调用它自己的AppDomain作用域跟踪.Write,以便(本地)侦听器能够正确显示消息
  • 注意事项:

    • AssemblyResolve确保在尝试引用包含此代码的程序集时出错
    • 此代码必须存在于两个进程中并共享同一命名空间。我在库中使用它,并将程序集引用添加到两个应用程序中
    • 还要注意Serializable属性和MarshallByRefObject继承。这是框架在AppDomains之间正确编组对象所必需的

    最后,您可以在一个静态类中整齐地打包所有这些内容

    
    公共静态类交叉域竞赛
    {
    公共静态侦听(AppDomain remoteDomain)
    {
    新的交叉域名赛车(remoteDomain);
    }
    }
    
    通过在将要注册远跟踪按摩的应用程序中执行此操作

    
    CrossDomainTrace.StartListening(应用域);
    
    剩下的唯一一件事就是在这一侧的Trace.Listeners集合中添加一个TraceListeners,以便对消息执行任何您想要的操作


    希望有帮助。

    有帮助。非常感谢。我最终将对TextWriter的引用从默认appDomain发送到remote,并在RemoteWrite方法中使用WriteLine。
    
    
        [Serializable]
        public sealed class CrossDomainTracer : MarshalByRefObject
        {
            private CrossDomainTracer remoteTracer;
            private SynchronizedTraceListener remoteListener;
    
            public CrossDomainTracer()
            {
            }
    
            public CrossDomainTracer(AppDomain farDomain)
            {
                AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
                this.remoteTracer = farDomain.CreateInstanceFrom(Assembly.GetExecutingAssembly().Location, typeof(CrossDomainTracer).FullName).Unwrap() as CrossDomainTracer;
                AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(CurrentDomain_AssemblyResolve);
                if (remoteTracer != null)
                {
                    remoteTracer.StartListening(this);
                }
            }
    
            public void StartListening(CrossDomainTracer farTracer)
            {
                this.remoteTracer = farTracer;
                this.remoteListener = new SynchronizedTraceListener(new TraceWriterHandler(Write));
                Trace.Listeners.Add(this.remoteListener);
            }
    
            public void Write(string message)
            {
                this.remoteTracer.RemoteWrite("AppDomain(" + AppDomain.CurrentDomain.Id.ToString() +") " + message);
            }
    
            public void RemoteWrite(string message)
            {
                Trace.Write(message);
            }
    
            Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                try
                {
                    Assembly assembly = System.Reflection.Assembly.Load(args.Name);
                    if (assembly != null)
                    {
                        return assembly;
                    }
                }
                catch { }
    
                // Try to load by assembly fullname (path to file)
                string[] Parts = args.Name.Split(',');
                string File = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + Parts[0].Trim() + ".dll";
    
                return System.Reflection.Assembly.LoadFrom(File);
            }
        }