20

I've written a Windows service in C# using the ServiceBase helper. During its execution, some procedures in an external native DLL are called. Annoyingly, those procedures write to stdout and/or stderr in an uncontrolled manner as no sources are given for this DLL.

Is it possible to redirect those outputs from the C# service to a log file?

Pang
  • 9,564
  • 146
  • 81
  • 122
Herchu
  • 325
  • 1
  • 4
  • 9

2 Answers2

31

You can do this via PInvoke to SetStdHandle:

[DllImport("Kernel32.dll", SetLastError = true) ]
public static extern int SetStdHandle(int device, IntPtr handle); 

// in your service, dispose on shutdown..
FileStream filestream;
StreamWriter streamwriter;

void Redirect()
{   
    int status;
    IntPtr handle;
    filestream = new FileStream("logfile.txt", FileMode.Create);
    streamwriter = new StreamWriter(filestream);
    streamwriter.AutoFlush = true;
    Console.SetOut(streamwriter);
    Console.SetError(streamwriter);

    handle = filestream.Handle;
    status = SetStdHandle(-11, handle); // set stdout
    // Check status as needed
    status = SetStdHandle(-12, handle); // set stderr
    // Check status as needed
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 3
    I've changed the line handle = filestream.Handler; by handle = filestream.SafeFileHandle.DangerousGetHandle(); because filestream.Handler is deprecated. – Herchu Oct 19 '09 at 15:36
  • 1
    Any way to use this without a FileStream? (i.e. MemoryStream or similar)? – Steve Dec 18 '11 at 21:27
  • @ReedCopsey - Please see my reply to a similar comment on my new question: http://stackoverflow.com/questions/8555002/redirecting-native-dlls-stdout-to-memory-stream – Steve Dec 18 '11 at 22:18
  • @Herchu you did realise the "Dangerous" in DangerousGetHandle? It is there for a reason: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.dangerousgethandle%28v=vs.100%29.aspx – Rui Marques Sep 01 '14 at 11:42
  • @RuiMarques Yeah, they call me Danger for a reason! :) Seriously now; that was 2009. If I happen to need it again I'll write it following Steve's solution. – Herchu Sep 03 '14 at 08:37
  • Regretfully, it does not work on Windows 10. The file is empty. I made sure that I Close() on both streamwriter and filestream when done. – eugen_nw Jul 12 '23 at 21:42
0

Check out the Console.SetOut method.

It will allow you to redirect console output to a TextWriter.

Pang
  • 9,564
  • 146
  • 81
  • 122
Jay Riggs
  • 53,046
  • 9
  • 139
  • 151