Search code examples
cwindowsconsolemingwmsys2

How does msys2 display console output from non-console application?


If I compile this source code:

#include <stdio.h>

int main(int argc, char* args[]) {
  printf("Done!\n");
  return 0;
}

with gcc hello.c -o hello -mwindows under msys2 using mingw-w64-x86_64-toolchain toolchain, and then run it from inside msys2 I'll see:

enter image description here

At the same time if I call this same executable from powershell (or cmd) I'll see:

enter image description here

To be honest, given the -mwindows which is saying to produce a windows executable as opposed to console one, I'm not surprised at the latter - I've seen it many times.

But how does msys2 manage to display that output?


Solution

  • There are very few differences between a console and GUI application on Windows and the C run-time stdio code usually does not care, it only cares about the standard Win32 handles.

    The main difference is how CreateProcess in the parent application works.

    • A console application gets hooked up to the parents standard Win32 handles if the parent has a console. If the parent does not have a console, a new console window is created for the application. The parent can pass optional flags to CreateProcess to force/deny a new console.

    • A GUI application is not hooked up to the standard Win32 handles and no new console is created.

    Powershell.exe is a real console application and it can use the default CreateProcess handling. Because your application is not a console application it will be created without standard handles and therefore it has nowhere to write to.

    The msys2 terminal application is probably not a real console application and probably calls CreateProcess with forced handles (STARTF_USESTDHANDLES). These handles are probably handles to pipes. Your application will see these handles as redirected stdio handles and execute in a similar fashion as how cmd.exe would perform yourconsoleapp.exe | otherconsoleapp.exe.