从 C# 中重定向本机 dll stdout/stderr
我正在尝试重定向第三方本机 dll 的输出,该 dll 从 C# 内输出到 stdout/stderr。 stdout 和 stderr 的输出都应保存到日志文件中。
这是我的想法(两个流 x2):
- 创建一个 AnonymousPipeServerStream
- 通过
_outServer.SafePipeHandle.DangerousGetHandle()获取管道的句柄
- 使用P/Invoke调用SetStdHandle 与所述句柄
- 创建一个 AnonymousPipeClientStream 连接到服务器流
- 创建一个线程以循环读取
AnonymousPipeClientStream
并输出到记录器。 - 定期在
AnonymousPipeServerStream
上调用flush
因此,这一切似乎在我的代码中运行良好。一旦控制权传递到本机 DLL,一切都会返回到 stderr!如果需要的话,我可以调试到本机 DLL 中,看看出了什么问题,但是......我真的不想,所以在我花 10 个小时试图弄清楚句柄如何工作之前,有人有任何想法吗?
作为参考,测试代码位于:http://pastebin.com/f3eda7c8。有趣的是构造函数中的第 58-89 行。 (当然,我稍后会添加错误处理等)。
I'm trying to redirect the output of a third-party native dll which outputs to stdout/stderr from within C#. The output of both stdout and stderr should go to a log file.
Here's my idea (x2 for two streams):
- Create an AnonymousPipeServerStream
- Get the pipe's handle via
_outServer.SafePipeHandle.DangerousGetHandle()
- Use P/Invoke to call SetStdHandle with said handle
- Create an AnonymousPipeClientStream connected to the server stream
- Create a thread to sit in a loop reading from the
AnonymousPipeClientStream
and outputting to the logger. - Periodically call
flush
on theAnonymousPipeServerStream
So all this seems to be working well... within my code. As soon as control passes to the native DLL, everything goes back to stderr! If need be, I can debug into the native DLL and see what's going wrong, but... I'd really rather not, so does anyone have any ideas before I spend 10 hours trying to figure out how handles work?
For reference, the test code is at: http://pastebin.com/f3eda7c8. The interesting stuff is lines 58-89 in the constructor. (I'll add error handling, etc. later, of course).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我解决了它,尽管解决方案(当然)与问题无关。该 dll 是在 mingw 中编译的,它显然不尊重 MSVC 运行时使用的句柄。
我会留下代码&解决方案以防其他人遇到此问题。
I solved it, though the solution (of course) has very little to do with the problem. The dll was compiled in mingw, which apparently doesn't respect the handles used by the MSVC runtime.
I'll leave the code & solution up in case anyone else encounters this problem.
使用 https://pastebin.com/f3eda7c8 上的代码我已经让它在 Windows 10 上运行并且在 Windows LTSC 2019 容器内。但是,它仅捕获 C# 代码的控制台输出,而不捕获非托管 DLL 的 printf 输出的痕迹,而这正是我希望达到的结果。我必须在 SetStdHandle 分配之后使用下面的 hack 才能使其工作 - 顺便说一句,我不太喜欢这个 hack。
谁能告诉我,我缺少什么才能将 printf 输出重定向到源自本机 .DLL 的控制台?我需要在每个
[f]printf
语句后添加fflush(stdout / stderr)
吗?或者只是在我有兴趣查看其输出返回的函数之前使用fflush(stdout);
和fflush(stderr);
?事实上,我在容器输出中看到的行之后添加了几个fflush(stdout);
调用,但这些本机printf
信息都没有被重定向。Using the code at https://pastebin.com/f3eda7c8 I've got it to work on Windows 10 and within a Windows LTSC 2019 container. However, it captures only the Console output of the C# code, not a trace of the unmanaged DLL's printf output which is the outcome that I desire to reach. I had to use the hack below after the SetStdHandle assignments in order to get it work - a hack that I do not really like BTW.
Could anyone please enlighten me on what is missing for me to get it to redirect the printf output to the Console that originates from the native .DLL? Do I need to add a
fflush(stdout / stderr)
after each[f]printf
statement? Or justfflush(stdout);
andfflush(stderr);
before the function I'm interested in seeing its output returns? As a matter of fact I added a couple offflush(stdout);
calls after lines I am seeing in the container's output but none of those nativeprintf
pieces of information got redirected.