gpt4 book ai didi

c# - 跨应用域访问 Console.Out

转载 作者:行者123 更新时间:2023-12-01 10:55:14 25 4
gpt4 key购买 nike

我需要读取在同一进程中但在不同 appDomain 中运行的应用程序(Core.exe)的标准输出。当处理进程时重定向输出很容易,但 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);
}
}
}

我已经尝试将 Console.Out 重定向到当前进程,假设如果应用程序共享相同的进程,则会有单个标准输出。

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

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

最佳答案

也许这可以帮助你。
我使用这些类能够监听远程 AppDomains Trace.(Write/WriteLine) 调用。

第一个类是允许我将 TraceListen Write/WriteLine 方法重定向到自定义委托(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 跟踪监听器类的核心。
这是棘手的部分。我会尽量不混淆解释。这对我来说很棘手,但它就在这里。
  • (本地)CrossDomainTracer 对象在远端 AppDomain 上创建(远端)CrossDomainTracer 对象。
  • (本地)CrossDomainTracer 对象调用(远)CrossDomainTracer 对象 .StartListening 并将其自身作为引用发送(本地)。
  • (远)CrossDomainTracer 对象开始监听(远)他的域中的任何 Trace.Write/WriteLine 调用。
  • 当进行(远)Trace.Write/WriteLine 调用时,它会从(本地)远程 AppDomain 调用 .RemoteWrite 方法。
  • (本地) .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);
    }
    }


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



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


    通过在将注册远 Trace 按摩的应用程序中执行此操作。



    CrossDomainTrace.StartListening(theFarAppDomain);


    剩下的唯一事情就是将 TraceListner 添加到这一侧的 Trace.Listeners 集合中,以对消息执行任何您想要的操作。

    希望能帮助到你。

    关于c# - 跨应用域访问 Console.Out,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15548364/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com