0

all!

Please, help me with any advice with my problem: I build GUI WinForms application and now I want to attach console to it. I found this is not as much easy as it seems before. But I found good solution here: How do I show a console output/window in a forms application? Below the code from rag answer.

using System;
using System.Runtime.InteropServices;

namespace SomeProject
{
    class GuiRedirect
    {
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool AttachConsole(int dwProcessId);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetStdHandle(StandardHandle nStdHandle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern FileType GetFileType(IntPtr handle);

    private enum StandardHandle : uint
    {
        Input = unchecked((uint)-10),
        Output = unchecked((uint)-11),
        Error = unchecked((uint)-12)
    }

    private enum FileType : uint
    {
        Unknown = 0x0000,
        Disk = 0x0001,
        Char = 0x0002,
        Pipe = 0x0003
    }

    private static bool IsRedirected(IntPtr handle)
    {
        FileType fileType = GetFileType(handle);

        return (fileType == FileType.Disk) || (fileType == FileType.Pipe);
    }

    public static void Redirect()
    {
        if (IsRedirected(GetStdHandle(StandardHandle.Output)))
        {
            var initialiseOut = Console.Out;
        }

        bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error));
        if (errorRedirected)
        {
            var initialiseError = Console.Error;
        }

        AttachConsole(-1);

        if (!errorRedirected)
            SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output));
    }
}

This code works as charm except one downside: non-latin letters outputs to console in strange encoding (but if redirected to file, they are in right encoding). I need to redirect both StdOut and StdErr, and if I change any part of the code it stops redirecting.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • Did you look at [SetConsoleOutputCP](https://learn.microsoft.com/en-us/windows/console/setconsoleoutputcp)? – Ken White Apr 01 '20 at 02:58
  • I guessing. But the font you are using may not support the encoding mode. See : https://www.pinvoke.net/default.aspx/kernel32.SetConsoleFont – jdweng Apr 01 '20 at 03:03
  • **Why** do you want a console? This feels like a XY Problem (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? – mjwills Apr 01 '20 at 03:21
  • @mjw: Attaching a console to a GUI process is a common way to allow an application to dump diagnostic information. – IInspectable Apr 01 '20 at 07:12
  • Indeed it is. If only we could be sure that was what @AlfofMelmac wanted it for... – mjwills Apr 01 '20 at 08:24
  • Check your Console code page using [`GetConsoleCP`](https://learn.microsoft.com/en-us/windows/console/getconsolecp). What's your Windows version? – Rita Han Apr 01 '20 at 09:42
  • And what's HEX values of those letters can't be display correctly? – Rita Han Apr 01 '20 at 09:44
  • Thanks a lot, guys! Looks like SetConsoleOutputCP resolved my problem (i'm not tested it on other Windows versions yet, but on my system (Win10/VS2017) all works as expected). – Alf of Melmac Apr 01 '20 at 13:32

1 Answers1

0

Thanks to all who share their wisdom with me in comments!

SetConsoleOutputCP was the answer.

Don't forget put this to other definitions of the class.

[DllImport("kernel32.dll")]
static extern bool SetConsoleOutputCP(uint wCodePageID);

And than add call of the SetConsoleOutputCP(desired codepage); to Redirect() method.