Re: Redirect stdout from unmanaged DLL

Tech-Archive recommends: Fix windows errors by optimizing your registry



"Thomas W. Brown" <thomas_w_brown@xxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:51BDF38C-9127-4B12-B254-1CCF3DDFC7D9@xxxxxxxxxxxxxxxx
> I don't think this will work in my case -- I've been scratching my head to
> try and figure out; 1) how I can do this from my managed code layer, and
> 2)
> even if I could, what to I supply as the low-level device handle that
> corresponds to my TextWriter that I use for the redirection.

Well, what I posted is a way to "wire" a "file" known to the C/C++ runtime
to an operating system handle. If you could have communicated the Win32
handle of the file to which you redirected your console, then my little hack
would have done the job.

> (1) is necessary because I do not have the ability to alter the unmanaged
> DLLs -- they are black boxes for me.

OK. There is almost always more than one way to skin a cat. The little C#
hack below does three things:

1) it points the Console at a file
2) it redirects the standard output device of the application to that file
using a bit of interop
3) it calls a function exported from DLL written in C++ which uses the plain
vanilla I/O stream for output

//--------------------------------------------------------------------------------------------------------------
using System;
using System.IO;
using System.Runtime.InteropServices;

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

[ DllImport("SayHello.dll") ]
public static extern void SayHello();

[STAThread]
static void Main(string[] args)
{
int status;
IntPtr handle;
FileStream fs;
StreamWriter sw;

fs = new FileStream("console.txt", FileMode.Create);

sw = new StreamWriter(fs);
sw.AutoFlush = true;
Console.SetOut(sw);

Console.WriteLine("This is a test of output via C#.");

handle = fs.Handle;
status = SetStdHandle(-11, handle);

SayHello();
}
}
}
//--------------------------------------------------------------------------------------------------------------

This is the source to the DLL I used to test the redirection:

//--------------------------------------------------------------------------------------------------------------
#include <windows.h>
#include <iostream>

void WINAPI SayHello()
{
std::cout << "This is a test of output in C++" << std::endl;
}
//--------------------------------------------------------------------------------------------------------------

Both lines were written to the file. That should do you, right?

> Thanks, though,

You are welcome.

Note that I/O is complicated. If the DLL had chosen to use the Win32 API
function WriteConsole() instead of the C++ I/O stream then it's I/O wouldn't
have been written to the file (at least I don't think so but I am frankly
too lazy and too busy now to test that).

Further if the call to SetStdHandle() does not precede the load of a DLL
whose output you want to capture then it will go to the real console instead
of the file.

Finally, the mysterious looking number -11 in the C# source is the manifest
constant STD_OUTPUT_HANDLE defined in <winbase.h>. I don't do enough interop
to know if there are .Net equivalents of such things. If there is one, I'm
all ears. :-)

Regards,
Will


.



Relevant Pages

  • Re: MFC DLL - ExitInstance hang on WaitForSingleObject
    ... Here is a simple pooling class implemented into a MFC DLL project. ... BOOL CPooler::StartPooling ... // Look for empty place in the array and create the Pooler ... void Enqueue(POOLER_CALLBACK_FN f, LPVOID p); ...
    (microsoft.public.vc.mfc)
  • Re: Calling a matlab dll in java
    ... you mention about putting a -nojvm option when initializing the dll ... the matlab generated library inside my jni-dll) ... all compiler and linker options in VS took me a while, ... JNIEXPORT void JNICALL ...
    (comp.soft-sys.matlab)
  • Re: create a wrapped managed dll that can be used from pure unmanaged code
    ... > code which calls into managed code" and some of those unmanaged ... Exporting a class based interface from a DLL ... public void SayHello() ... GCHandle gch; ...
    (microsoft.public.dotnet.languages.vc)
  • Re: Calling a matlab dll in java
    ... I compiled it with mcc to dll shared library ... all compiler and linker options in VS took me a while, ... JNIEXPORT void JNICALL Java_JNITest_JNITest_initializeApplication ... public void launchThread() ...
    (comp.soft-sys.matlab)
  • Re: Problem using WndProc MessageWindow with native DLL
    ... what you are doing is calling a DLL function from ... > private System.Windows.Forms.Button Identify; ... > protected override void Dispose(bool disposing) ... > private void InitializeComponent() ...
    (microsoft.public.dotnet.framework.compactframework)