7

I have a third-party dll that I load into software that isn't mine, and I'm using AllocConsole() to create the standard windows CLI window so I have an easy means of outputting debug messages.

My problem is though, is that it ignores any kind of input. I just want to be able to use the console I allocated and enable the ability for me to give it some input.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
Nowayz
  • 1,882
  • 4
  • 21
  • 34

4 Answers4

16

Thanks to Ben Voigt, I was able to cause the console to take input after I allocated it by doing:

freopen("CONIN$", "r", stdin); 
freopen("CONOUT$", "w", stdout); 
freopen("CONOUT$", "w", stderr); 

This also directs the stdout and strerr to the same console window, in case they are directed someplace else for some reason.

Nowayz
  • 1,882
  • 4
  • 21
  • 34
  • 2
    In case it helps anyone, with VS2013 I was unable to get the console to close via FreeConsole without "putting back" stdout/stderr:freopen("OUT", "w", stdout); – tmruss Nov 27 '16 at 10:52
  • `freopen("NUL", "w", stdout)` is better... "OUT" creates a file named "OUT" in current folder, whereas NUL is null output, so discards everything. `CONOUT$` might be better still... not sure how that one works. – Phi May 31 '19 at 00:55
  • Beware of issues in `freopen` implementation of `UCRT`: 1. It does not reuse 0-2 descriptors, to reuse them you have to close them first: `const int stdin_fileno = _fileno(stdin); fclose(stdin); if (stdin_fileno < 0) _close(STDIN_FILENO);`. 2. In case of not console application (GUI) it will ignore `SetStdHandle` (`_dup2` ignores it too), you have to excplicitly call it. – Andry Jul 31 '21 at 07:54
3

This is what I use.

    FILE *file = nullptr;
freopen_s(&file,"CONIN$", "r", stdin);
freopen_s(&file, "CONOUT$", "w", stdout);

Just hopes this helps someone.

2

Do you also redirect the stdoutand stderrto your console?

I used this code to get access to the JavaVM output from a Windows app.

if(::AllocConsole())
    {
        int hCrt = ::_open_osfhandle((intptr_t) ::GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
        FILE *hf = ::_fdopen( hCrt, "w" );
        *stdout = *hf;
        ::setvbuf(stdout, NULL, _IONBF, 0 );

        hCrt = ::_open_osfhandle((intptr_t) ::GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
        hf = ::_fdopen( hCrt, "w" );
        *stderr = *hf;
        ::setvbuf(stderr, NULL, _IONBF, 0 );
    }

After this I can see all stdoutand stderr outputs from the VM.

mkaes
  • 13,781
  • 10
  • 52
  • 72
  • I've directed the stdout and stderr yes, but I still can't use the CLI window for STDIN. When I try to set the stdin correctly the window still refuses to be typed on. – Nowayz Jan 26 '12 at 15:57
  • The standard handles aren't associated with a console created after the program starts. If that were done first, the rest of this might work. – Ben Voigt Jan 26 '12 at 17:28
2

This is the code that works for me:

freopen("CONOUT$", "w", stdout);

You can probably do something similar with CONIN$ and stdin (Open for read, of course).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720