首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跨应用程序域访问Console.Out

跨应用程序域访问Console.Out
EN

Stack Overflow用户
提问于 2013-03-21 21:02:47
回答 1查看 2.5K关注 0票数 3

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

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

代码语言:javascript
复制
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.Out,假设如果应用程序共享相同的进程,将会有单一的标准输出。

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

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-22 00:22:12

也许这能帮到你。我使用这些类来监听远程AppDomains跟踪(Write/WriteLine)调用。

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

代码语言:javascript
复制
    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跟踪侦听器类的核心。这就是棘手的部分。我会尽量不把解释搞乱的。这对我来说很棘手,但它开始了。

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

备注:

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

代码语言:javascript
复制
    [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);
        }
    }

最后,您可以将所有这些都整齐地打包到一个静态类中。

代码语言:javascript
复制
    public static class CrossDomainTrace
    {
        public static void StartListening(AppDomain remoteDomain)
        {
            new CrossDomainTracer(remoteDomain);
        }
    }

通过在将注册远距离跟踪消息的应用程序中执行此操作。

代码语言:javascript
复制
    CrossDomainTrace.StartListening(theFarAppDomain);

剩下的唯一一件事就是在这一端的Trace.Listeners集合中添加一个TraceListner,以便对消息做任何您想做的事情。

希望能有所帮助。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15548364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档