跨应用程序域访问Console.Out [英] Cross-appDomain access to Console.Out

查看:73
本文介绍了跨应用程序域访问Console.Out的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要读取以相同过程运行但在不同appDomain中运行的应用程序(Core.exe)的标准输出.当一个人处理过程时,重定向输出是很容易的,但是appDomains概念对我来说是新的.

I need to read standart output from application (Core.exe) that runs in the same process but in different appDomain. It's quite easy to redirect output when one deals with process but the appDomains concept is new to me.

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

So.. I start application in isolataed appDomain like that

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);
        }
    }
}

我已经尝试重定向Console.假设应用共享相同的进程,则将退出当前进程.

I've tride to redirect Console.Out of the current process assuming that if the apps share the same process there will be single standart output.

但是它仅显示默认的appDomain标准输出.

But it only shows the default appDomain standart output.

因此,总结起来,我需要访问另一个appDomain应用程序标准输出.还是有办法从核心" appDomain调用默认appDomain中的方法?

So, to sum it up I need to gain access to another appDomain application standart output. Or may be there is a way to call a method located in default appDomain from "core" appDomain?

推荐答案

也许这可以为您提供帮助. 我使用这些类来侦听远程AppDomains跟踪.(Write/WriteLine)调用.

Maybe this can help you. I use these classes to be able to listen to remote AppDomains Trace.(Write/WriteLine) calls.

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

The first class is a class that allows me to redirect the TraceListen Write/WriteLine methods to a custom delegate.



    public delegate void TraceWriterHandler(string message);

    internal class SynchronizedTraceListener : TraceListener
    {
        private TraceWriterHandler messageHandler;

        public SynchronizedTraceListener(TraceWriterHandler writeHandler)
        {
            messageHandler = writeHandler;
        }

        public override void Write(string message)
        {
            messageHandler(message);
        }

        public override void WriteLine(string message)
        {
            messageHandler(message + System.Environment.NewLine);
        }
    }

然后是我的远程AppDomain跟踪侦听器类的核心. 这是棘手的部分.我将尽量避免弄乱解释.这对我来说很棘手,但是就在这里.

Then the core of my remote AppDomain trace listener class. This is the tricky part. I'll try not to mess the explanation. This is tricky for me to, but here it goes.

  1. (本地)CrossDomainTracer对象在远端AppDomain上创建一个(远)CrossDomainTracer对象.
  2. (本地)CrossDomainTracer对象调用(远)CrossDomainTracer对象.StartListening并自行发送(本地)它作为参考.
  3. (far)CrossDomainTracer对象开始侦听其域中(far)的任何Trace.Write/WriteLine调用.
  4. 调用(far)Trace.Write/WriteLine时,它会从(本地)远程AppDomain调用.RemoteWrite方法.
  5. (本地).RemoteWrite对其自身的AppDomain范围Trace.Write进行调用,以便(本地)侦听器可以正确显示消息.

注释:

  • AssemblyResolve确保在尝试引用包含此代码的程序集时出错.
  • 此代码必须在两个进程中都存在并且共享相同的名称空间.我在库中使用它,并将程序集引用添加到两个应用程序中.
  • 还请注意Serializable属性和MarshalByRefObject继承.框架要求在AppDomain之间正确编组对象.



    [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);
        }
    }

最后,您可以将所有内容整齐地打包在静态类中.

Finnaly you can neatly pack all this in a static class.



    public static class CrossDomainTrace
    {
        public static void StartListening(AppDomain remoteDomain)
        {
            new CrossDomainTracer(remoteDomain);
        }
    }

通过在将要记录远距Trace按摩的应用中执行此操作.

By doing this in the app that will be registering the far Trace massages.



    CrossDomainTrace.StartListening(theFarAppDomain);

剩下的唯一一件事就是将TraceListner添加到这一侧的Trace.Listeners集合中,以完成您想对消息进行的操作.

The only thing left is to add a TraceListner to the Trace.Listeners collection on this side to do what ever you want with the messages.

希望有帮助.

这篇关于跨应用程序域访问Console.Out的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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