我需要读取以相同过程运行但在不同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.
注释:
- 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
发布评论