Reputation: 10927
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):
_outServer.SafePipeHandle.DangerousGetHandle()
AnonymousPipeClientStream
and outputting to the logger.flush
on the AnonymousPipeServerStream
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).
Upvotes: 7
Views: 2721
Reputation: 159
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 just fflush(stdout);
and fflush(stderr);
before the function I'm interested in seeing its output returns? As a matter of fact I added a couple of fflush(stdout);
calls after lines I am seeing in the container's output but none of those native printf
pieces of information got redirected.
private void _ResetConsoleOutStream()
{
//Force console to recreate its output stream the next time Write/WriteLine is called
typeof(Console).GetField("_out", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, null);
}```
Upvotes: 0
Reputation: 10927
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.
Upvotes: 3