【问题标题】:Can I redirect output from a C DLL into my c# log4net output我可以将 C DLL 的输出重定向到我的 c# log4net 输出吗
【发布时间】:2015-04-04 13:41:45
【问题描述】:

我有一个 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); 虽然,我不知道那是做什么的,但它并没有起到我的作用想。我想我也需要一个类似的标准错误行。无论哪种情况,google 似乎都认为这些行只是负责缓冲而不是重定向到 log4net。

我假设我需要某种函数覆盖来阻止控制台写入(从加载的另一种语言的 DLL)并将它们转换为 mLog.InfoFormat("{0}", consoleString); 类型的调用。我是 c# 的新手,甚至不确定谷歌需要哪些条款才能找到这样的覆盖(如果可能的话)。

不确定这是否会使问题复杂化,但我的 C# 应用程序是多线程的,并且一些 DLL 也有多个线程。我假设这只是意味着我需要在处理控制台输出并将其写入 log4net 框架(可能)的方法中使用某种锁,或者 log4net 的正常序列化可能会为我处理它。

【问题讨论】:

  • SetStdHandle
  • 如何知道 DLL 是用 C 还是 C++ 编写的?
  • 我在编写 DLL 时拥有顶层几层 DLL 的源代码。在幕后,这些 DLL 最终会为 CURL 和 FFMPEG 等加载 DLL。但是,最上面的两层 DLL 是我的,是用 C 和 C++ 编写的。如果解决方案需要,我可以修改它们。
  • 这里是my code example

标签: c# c++ c dll log4net


【解决方案1】:

一旦我弄清楚如何使用它们,它们就成功了。我设置了两个命名管道(或同一管道的两端?)。我连接到 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等)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2017-05-15
    • 2022-10-20
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    相关资源
    最近更新 更多