7

I'm using MinGW to build my application on Windows. When compiling and linking, the option "-mwindows" is put in command line to have Win32 API functions.

To be more specific: when calling GCC of MinGW without "-mwindows" like this:

c:\>g++ -c main.cpp 
c:\>g++ -o main.exe main.o

The 'main.exe' after the 2 command lines above will run with a console, and Win32 API functions won't be usable.

When calling GCC of MinGW with "-mwindows" like this:

c:\>g++ -c main.cpp
c:\>g++ -o main.exe main.o -mwindows

Now linking with '-mwindows', the 'main.exe' can use Win32 API, however, it doesn't start a console when the application runs.

This "-mwindows" option disables the console, which makes me not able to print out debugging info. Any way to keep both console and the option '-mwindows'?

jondinham
  • 8,271
  • 17
  • 80
  • 137
  • possible duplicate of [How do I print to the debug output window in a Win32 app?](http://stackoverflow.com/questions/1333527/how-do-i-print-to-the-debug-output-window-in-a-win32-app) – rubenvb Oct 27 '12 at 14:03
  • @rubenvb, no no, this isn't related to Visual Studio – jondinham Oct 27 '12 at 14:16
  • 2
    It's not the same. Here we don't talk about debugging output. Part of the answers may overlap, but it's not exact duplicate. And some answers there are specific to VS. – Jarekczek Oct 27 '12 at 14:56
  • yes. i build and run from command-line, no debugger – jondinham Oct 27 '12 at 14:56

4 Answers4

18

The -mconsole switch is used to specify that you want to target the console subsystem. You really do want to do that to ensure that your process connects to the existing console if started from a console app. For example, suppose you do go down your route of targeting the GUI subsystem, and then calling AllocConsole(), as per your own answer. Then you'll find your app shows a brand new console rather than using the existing one when started from another console app, e.g. cmd.exe.

If you need to use other libraries, then you are free to add them on command line using -l. There's nothing special about a console app that means that it cannot link to any Win32 API function. It's just that the default set of libraries associated with -mconsole is missing some of the libraries that you want.

On the other hand, you can use both -mconsole and -mwindows when you build your app. They are not mutually exclusive.

gcc -mconsole -mwindows main.c

This produces an application that targets the console subsystem. And you get the standard -mwindows set of Win32 libraries automatically linked. It's probably the simplest way to achieve your goal.

Braden Steffaniak
  • 2,053
  • 3
  • 25
  • 37
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • i tried to add -mconsole when linking but the console didn't appear – jondinham Oct 28 '12 at 03:23
  • @PaulDinh Er, it does for me. I took @Jarekczek's program and compiled it exactly as per my updated answer. That outputs a console subsystem. You really do not want to do it using `AllocConsole`. Not unless you want 2 console windows!! – David Heffernan Oct 28 '12 at 09:57
  • I would never think of joining these 2 `-m` switches. If it's possible, then it is the best option indeed. – Jarekczek Oct 28 '12 at 18:05
  • Thanks for this. Had no idea you could use both options – Alex Jan 26 '18 at 05:28
7

I have no evidence for this answer, only a bit of experiments that were successful. If I have a hello app, like this:

#include <stdio.h>
#include <windows.h>

int main(void)
{
    puts("hi");
    MessageBox(NULL, "test", "test", NULL);
    GetStockObject(0);
    return 0;
}

I cannot compile it with -mconsole, because linker complains about GetStockObject. But when I add the necessary library with -lgdi32 switch on my command line, the app compiles and executes cleanly. Maybe this is the way to keep both console and gdi. This is the command line:

gcc -mconsole test_gdi.c -lgdi32
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Jarekczek
  • 7,456
  • 3
  • 46
  • 66
3

I found the answer. As taken from Using STDIN with an AllocConsole()

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

It works like magic!

Reference for 'freopen': http://www.cplusplus.com/reference/clibrary/cstdio/freopen/

Community
  • 1
  • 1
jondinham
  • 8,271
  • 17
  • 80
  • 137
  • 2
    That won't do what you want if your app is started up from, for example, a command prompt that already has a console attached. – David Heffernan Oct 27 '12 at 17:00
  • Did you try it out yet? This approach results in two consoles. – David Heffernan Oct 28 '12 at 09:45
  • typo. i meant to reply as -mconsole, the option -mwindows seems to make -mconsole no longer effective as on my mingw – jondinham Oct 28 '12 at 15:22
  • That produces a console subsystem app for me. – David Heffernan Oct 28 '12 at 15:23
  • 1
    Which version of mingw are you using? Anyway, I've made my point. You need to produce an exe that targets the console subsystem. I can use both -mconsole and -mwindows to achieve that. If you cannot, then use -mconsole and add the other libs with -l. – David Heffernan Oct 28 '12 at 15:30
  • i'm using mingw v3.2 (latest release) which comes with gcc v4.7 – jondinham Oct 28 '12 at 15:45
  • 1
    I've got 4.6.3. I'm using the MS tool `dumpbin /headers` to check the subsystem of the output exe. – David Heffernan Oct 28 '12 at 15:49
  • +1 This answer (AllocConsole) was the only way I was able to get a console for a Windows GUI program with Code::Blocks 16.01 and mingw. "-mconsole" was ignored if "-mwindows" is passed, and I can't compile without -mwindows despite manually passing "-lgdi32 -luser32 -lkernel32 -lcomctl32 -lole32 -lcomdlg32". Being unable to replace -mwindows with linking libs manually occurs when you're using Win32 functions from a static library; since Code::Blocks places your static library AFTER the -l linker options, the linker doesn't know you needed functions from the windows libraries and strips them! – Dennis Jun 22 '16 at 22:31
  • @DavidHeffernan you could use `if (!AttachConsole(ATTACH_PARENT_PROCESS)) { AllocConsole(); }`. First try to attach to the parent's console. If this fails create a new one. – urbanSoft Nov 18 '22 at 08:32
0

You need to manually capture hInstance and nCmdShow (WinMain arguments). You can use the following C functions to do this:

HINSTANCE GetHInstance( ) {
   return (HINSTANCE) GetModuleHandleW(NULL);
}
    
int GetNCmdShow() {
   STARTUPINFOW startupInfo;
   GetStartupInfoW(&startupInfo);
   if ((startupInfo.dwFlags & STARTF_USESHOWWINDOW) != 0) {
      return startupInfo.wShowWindow;
   }
   return SW_SHOWDEFAULT;
}
Community
  • 1
  • 1
annoying_squid
  • 513
  • 5
  • 10