草庐IT

c# - 我可以将 C DLL 的输出重定向到我的 c# log4net 输出吗

coder 2024-02-25 原文

我有一个 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 并重定向它,为那个使用错误日志。可能想要摆脱魔数(Magic Number) (-11) 并使用普通枚举(STD_ERROR_HANDLE 等)

关于c# - 我可以将 C DLL 的输出重定向到我的 c# log4net 输出吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28331470/

有关c# - 我可以将 C DLL 的输出重定向到我的 c# log4net 输出吗的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  6. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  7. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  8. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

随机推荐