OutputDebugString() in console
Asked Answered
M

1

9

I am using a third party library that uses the function OutputDebugString(), and when reading the MSDN documentation it seems to indicate that this is for printing to the debugger.

But that is inconvenient in my case, is there a way to read this output if there is no debugger connected?

If it was my LIB, I would prefer the output to go to stdout/stderr whenever the user passes --debug or similar, but since it's not I am looking for other ways to pass this info to the console (or file) without connecting a debugger.

Margo answered 4/1, 2017 at 14:17 Comment(4)
try dbgview, it will capture the output string, with many other featuresCreosote
if you want do this "* read this output *" programmatically - this is possible - you need set VEX handler and spy for DBG_PRINTEXCEPTION_[WIDE_]C - if you want I can paste code for redirect OutputDebugString to console - this is small and simplyLesotho
@Lesotho sure - that could be useful.Margo
Try DebugView++. Much faster than DebugView, and has some pretty useful formatting and filtering options.Interdental
L
10

the OutputDebugStringA generate exception DBG_PRINTEXCEPTION_C (W version in win10 - DBG_PRINTEXCEPTION_WIDE_C) with 2 arguments - (string length in characters + 1, string pointer) - as result we can handle this exception yourself (system default handler for this exception do this).

example handler for redirect OutputDebugString to console:

LONG NTAPI VexHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
    PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;

    switch (ExceptionRecord->ExceptionCode)
    {
    case DBG_PRINTEXCEPTION_WIDE_C:
    case DBG_PRINTEXCEPTION_C:

        if (ExceptionRecord->NumberParameters >= 2)
        {
            ULONG len = (ULONG)ExceptionRecord->ExceptionInformation[0];

            union {
                ULONG_PTR up;
                PCWSTR pwz;
                PCSTR psz;
            };

            up = ExceptionRecord->ExceptionInformation[1];

            HANDLE hOut = GetStdHandle(STD_ERROR_HANDLE);

            if (ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
            {
                // localized text will be incorrect displayed, if used not CP_OEMCP encoding 
                // WriteConsoleA(hOut, psz, len, &len, 0);

                // assume CP_ACP encoding
                if (ULONG n = MultiByteToWideChar(CP_ACP, 0, psz, len, 0, 0))
                {
                    PWSTR wz = (PWSTR)alloca(n * sizeof(WCHAR));

                    if (len = MultiByteToWideChar(CP_ACP, 0, psz, len, wz, n))
                    {
                        pwz = wz;
                    }
                }
            }

            if (len)
            {
                WriteConsoleW(hOut, pwz, len - 1, &len, 0);
            }

        }
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}

and for set this handler need call:

AddVectoredExceptionHandler(TRUE, VexHandler);

the system implementation of OutputDebugString like here - it really called RaiseException with exactly this arguments, only in exception handler instead MessageBox - code described here.

Lesotho answered 5/1, 2017 at 9:1 Comment(3)
your solution doesn't work. OutputDebugString does not generate exception you mention.Bathsheb
YOU ARE RIGHT, I WAS WRONG. INDEED DBG_PRINTEXCEPTION_WIDE_C IS GENERATED. I tested it again, I made mistake. Sorry. I will not delete previous comment to not confuse others.Bathsheb
@SonnyD - i almost sure that you test under debugger. exception of course generated and in this case, but debugger handle this exception and as result you not view it in code. exception handler not calledLesotho

© 2022 - 2024 — McMap. All rights reserved.