我有一个C#应用程序,它反过来加载一个C或C dll(它反过来加载其他C/C++ dll).在C#应用程序中,我使用log4net记录器将所有输出捕获到一系列日志文件中.我的应用程序作为Windows服务运行,因此没有正常printfs的控制台/输出窗口或写入stdout / stderr的输出.
有没有办法设置C#应用程序来引导stdout / stderr(来自DLL)并将每一行转换为log4net输出.或者在C/C++ DLL中是否有某种方法将stdout / stderr流连接到log4net输出?
我找到了一些解决方案(这里:http://bytes.com/topic/c-sharp/answers/822341-dllimport-stdout-gets-eaten)表示我需要调用我的C DLL,如下所示:setvbuf(stdout,NULL,_IONBF,0);虽然,我不知道它做了什么,但它没有做我想要的.我想我也需要一个类似的stderr线.在任何一种情况下,谷歌似乎认为这些行只是照顾缓冲而不是重定向到log4net.
我假设我需要某种函数覆盖,它会阻塞控制台写入(从另一种语言加载的DLL)并将它们转换为mLog.InfoFormat(“{0}”,consoleString);各种各样的电话.我是c#的新手,甚至不确定谷歌的哪些条款才能找到这样的覆盖(如果它甚至可能).
不确定这是否使问题复杂化,但我的C#应用程序是多线程的,并且一些DLL也有多个线程.我假设这只是意味着我需要在处理控制台输出的方法内部进行某种锁定并将其写入log4net框架(可能)或者正常的log4net序列化将为我处理它.
解决方法:
事实证明,一旦我弄清楚如何使用它们,那些就完成了.我设置了两个命名管道(或同一管道的两端?).一个我连接到stdout并让它在log4net中执行任何来自管道的日志消息.
internal static void InfoLogWriter(Object threadContext)
{
mLog.Info("InfoLogWriterthread started");
int id = Process.GetCurrentProcess().Id; // make this instance unique
var serverPipe = new NamedPipeServerStream("consoleRedirect" + id, PipeDirection.In, 1);
NamedPipeClientStream clientPipe = new NamedPipeClientStream(".", "consoleRedirect" + id, PipeDirection.Out, PipeOptions.WriteThrough);
mLog.Info("Connecting Client Pipe.");
clientPipe.Connect();
mLog.Info("Connected Client Pipe, redirecting stdout");
HandleRef hr11 = new HandleRef(clientPipe, clientPipe.SafePipeHandle.DangerousGetHandle());
SetStdHandle(-11, hr11.Handle); // redirect stdout to my pipe
mLog.Info("Redirection of stdout complete.");
mLog.Info("Waiting for console connection");
serverPipe.WaitForConnection(); //blocking
mLog.Info("Console connection made.");
using (var stm = new StreamReader(serverPipe))
{
while (serverPipe.IsConnected)
{
try
{
string txt = stm.ReadLine();
if (!string.IsNullOrEmpty(txt))
mLog.InfoFormat("DLL MESSAGE : {0}", txt);
}
catch (IOException)
{
break; // normal disconnect
}
}
}
mLog.Info("Console connection broken. Thread Stopping.");
}
还有一个函数将所有这些推送到另一个线程,因此当它遇到各种阻塞调用时它不会阻塞我的主线程.
internal static void RedirectConsole()
{
mLog.Info("RedirectConsole called.");
ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(InfoLogWriter));
// TODO enqueue and item for error messages too.
}
我无法断开连接并且必须重新连接管道,但我会找出一个重新连接解决方案.我猜这种情况发生在DLL被换回内存时,或者当我需要读取时,但目前还没有任何东西可以读取?我还必须设置另一对来阻止stderr并重定向它,使用错误日志.可能想要摆脱幻数(-11)并使用普通的枚举(STD_ERROR_HANDLE等)