Skip to content

Instantly share code, notes, and snippets.

@flysand7
Created March 13, 2023 17:27
Show Gist options
  • Save flysand7/a3a91ab30d28584b02ed3600ddad712d to your computer and use it in GitHub Desktop.
Save flysand7/a3a91ab30d28584b02ed3600ddad712d to your computer and use it in GitHub Desktop.
win32 console/window app
// Sometimes there is a need to make an application that behaves like a GUI app when ran via
// explorer, but like console application when ran from console. This file implements such
// an application. On start, it will try to attach to a parent console. If that failed,
// that means that we ran from explorer, and we may want to allocate a console for debugging
// purposes. If we get a console either by attaching to it or by creating it, we will redirect
// std handles.
// At program termination we need to send enter to stdin in order to let the parent console
// know that we're done. I'm not sure why we need to do this but if it's not done, the parent
// will wait indefinately for user input.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#if defined(DEBUG_CONSOLE)
const bool do_open_debug_console = true;
#else
const bool do_open_debug_console = false;
#endif
static bool win32_setup_console() {
if(!AttachConsole(ATTACH_PARENT_PROCESS)) {
if(do_open_debug_console) {
if(!AllocConsole()) {
return false;
}
}
else {
return true;
}
}
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hstderr = GetStdHandle(STD_ERROR_HANDLE);
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
if(hstdout == INVALID_HANDLE_VALUE) {
return false;
}
if(hstderr == INVALID_HANDLE_VALUE) {
return false;
}
if(hstdin == INVALID_HANDLE_VALUE) {
return false;
}
if(freopen("CONOUT$", "w", stdout) == NULL) {
return false;
}
if(freopen("CONOUT$", "w", stderr) == NULL) {
return false;
}
if(freopen("CONIN$", "r", stdin) == NULL) {
return false;
}
setvbuf(stderr, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
return true;
}
static void win32_send_enter(void) {
INPUT_RECORD in_buffer[2] =
{
{
.EventType = KEY_EVENT,
.Event.KeyEvent = {
.bKeyDown = 1,
.wVirtualKeyCode = VK_RETURN,
.wVirtualScanCode = MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_VSC),
.uChar.AsciiChar = MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_CHAR),
},
},
{
.EventType = KEY_EVENT,
.Event.KeyEvent = {
.bKeyDown = 0,
.wVirtualKeyCode = VK_RETURN,
.wVirtualScanCode = MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_VSC),
.uChar.AsciiChar = MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_CHAR),
},
},
};
DWORD written;
WriteConsoleInput(
GetStdHandle(STD_INPUT_HANDLE),
&in_buffer[0],
2,
&written
);
}
int WINAPI wWinMain(HINSTANCE inst, HINSTANCE pinst, PWSTR cmdline, int show) {
if(!win32_setup_console()) {
MessageBoxA(NULL, "Unable to find or create console", NULL, MB_OK);
ExitProcess(1);
}
printf("Hello, world!\n");
win32_send_enter();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment