9dan
9dan

Reputation: 4272

How to execute child console programs without showing the console window from the Win32 GUI program?

(I've searched SO answers and found no clear solution to this problem.)

I'm working on a MFC GUI program. This program runs various child programs including console program and shell command script(.cmd).

Initially it displayed one GUI window and one console window (created with AllocConsole) because there are many console output from the child processes. But many users complained about the console window so we decided to hide the console window.

Firstly tried like below:

if (AllocConsole())
{
    ::ShowWindow(::GetConsoleWindow(), SW_HIDE);
}

Okay, no console window but there are visible flicker at the console creation time. I've tried several CreateProcess options for child process creation to prevent showing of console window altogether but failed at short and I think it is practically impossible.

It is not a big deal. We can ignore temporary window flicker at the startup.

But is it really impossible to hide child console window completely?

Upvotes: 11

Views: 12866

Answers (2)

Tinmarino
Tinmarino

Reputation: 4031

CREATE_NO_WINDOW is the key, in my tests, it also detaches the process from the parent so that the child survives the parent death, a Zombie process.

#include <windows.h>  // What would I do without you


STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;

if (!CreateProcess(
    NULL,             // [in, optional]      LPCSTR                lpApplicationName,
    s_command,        // [in, out, optional] LPSTR                 lpCommandLine,
    NULL,             // [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
    NULL,             // [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
    FALSE,            // [in]                BOOL                  bInheritHandles,
    CREATE_NO_WINDOW, // [in]                DWORD                 dwCreationFlags,
    NULL,             // [in, optional]      LPVOID                lpEnvironment,
    NULL,             // [in, optional]      LPCSTR                lpCurrentDirectory,
    &si,              // [in]                LPSTARTUPINFOA        lpStartupInfo,
    &pi               // [out]               LPPROCESS_INFORMATION lpProcessInformation
    )){
  print("Failed to create process\n");
  return 1;
}

// Wait until child process exits.
// WaitForSingleObject( pi.hProcess, INFINITE );

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
print("Succeded to create process\n");

Thanks to @9dan comment above.

Upvotes: 0

John
John

Reputation: 5635

Setup the STARTUPINFO like this for the CreateProcess call:

    STARTUPINFO si = { 0 };
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput =  GetStdHandle(STD_OUTPUT_HANDLE);
    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    si.wShowWindow = SW_HIDE;

Upvotes: 16

Related Questions