Home > Software engineering >  FreeConsole() does not detach application from cmd
FreeConsole() does not detach application from cmd

Time:10-07

I launch my application in cmd. I compiled it by Cmake without WIN32_EXECUTABLE, so it hangs in cmd (i.e. is launched as not detached). Now I want to close the console and try to achieve this by calling FreeConsole().

This works in case I double-click the application -- the black console is flashes quickly and gets closed. But it does not work when I launch it in cmd. The cmd is still attached to the launched application and FreeConsole() does not help.

Is there any way to detach it from cmd programmatically? I have found the opportunity to run start /b myapp, but I would like to do it in a programmatical way.

CodePudding user response:

Creating a "perfect" application that can be both GUI or console is not possible on Windows.

When a .exe has its subsystem set to console, two things happen:

  • CreateProcess will attach it to the parents console. If the parent does not have one, a new console is created. This can only be suppressed by passing flags to CreateProcess.
  • cmd.exe will wait for the process to finish.

The trick of setting the subsystem to Windows and using AttachConsole is sub-optimal because cmd.exe will not wait.

The best solution is to create your main .exe as a Windows application. Create another console helper application that you rename from .exe to .com. The helper application will just launch the main app in GUI mode and then quit. In console mode it has to tell the main app that it needs to attach and you need to WaitForSingleObject on it.

Visual Studio uses this .com trick. The trick works because .com is listed before .exe in %pathext%.

CodePudding user response:

I can add some instructions for the main application and the waitforsingleobject section. The answer above which means cooperation between threads in the main program. When the helper calls CreateProcess a PROCESS_INFORMATION is filled with a handle to the child process, pass this and INFINITE to WaitForSingleObject. I can use WaitForMultipleObjects to write a sample to help you understand.

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
...................
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
....................
}
int main()
{
    HANDLE hThread[2];
    DWORD dWResult1;
    DWORD dWResult2;
    hThread[0] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    hThread[1] = CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
    

    WaitForMultipleObjects(2,hThread,true,INFINITE);

============================================
just a sample which stops and closes threads, here can call `AttachConsole` to replace the following code` 
===========================================

    GetExitCodeThread(hThread[0], &dWResult1);
    GetExitCodeThread(hThread[1], &dWResult2);
    printf("Thread execution completed \n");
    getchar();
    CloseHandle(hThread[0]);
    CloseHandle(hThread[1]);

    return 0;
}

Then you can use the attachconsole and other code you need to execute to replace the programs I wrote to abort the exit.

  • Related