Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QProcess close child processes issue



  • Hi! I want to close/terminate the Inno Setup installation process using my application. I have tried these methods of QProcess:

    close(), terminate(), kill() but it only closes the 1 process and all child Inno Setup processes continue running. How to close all Inno Setup processes? Any ideas? Thanks.



  • I fixed it using the Win API.

    Code:

          DWORD pid = NULL;
          HWND hWnd = FindWindow(NULL,  QString("SetupTitle").toStdWString().c_str());
          GetWindowThreadProcessId(hWnd, &pid);
          HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, TRUE, pid);
          DWORD res = TerminateProcess(handle, NULL);
    
          if (res == NULL) {
              QMessageBox::critical(this, QObject::tr("Error"), QObject::tr("Process is not found."), QMessageBox::Ok);
          } 
    
          CloseHandle(handle);
    

    Info:

    1. It gets the pid from the window title
    2. Creates the handle with the process pid
    3. Terninates the process using TerminateProcess function
    4. Closes the handle

    Also I added the additional check if process is not detected. The issue is resolved.



  • This solution works but it has some cons. For example, you need manually specify the window title in the FindWindow function, add some checking if it's localized in the different languages etc.

    So, I have checked the Microsoft Spy++ app, read some docs, then I have created another solution.

    Code:

            DWORD pid = NULL;
            HWND hWnd = FindWindow(QString("TWizardForm").toStdWString().c_str(), NULL);
            std::wstring title;
            title.reserve(GetWindowTextLength(hWnd) + 1);
            GetWindowText(hWnd, const_cast<WCHAR *>(title.c_str()), title.capacity());
            HWND wizardhWnd = FindWindowEx(NULL, NULL, QString("TWizardForm").toStdWString().c_str(), title.c_str());
            GetWindowThreadProcessId(wizardhWnd, &pid);
            
            HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, TRUE, pid);
            DWORD res = TerminateProcess(handle, NULL);
    
            if (res != NULL) {
                QMessageBox::information(this, "Information", "Process has been closed!", QMessageBox::Ok);
            } else {
                QMessageBox::critical(this, "Error", "Process is not found!", QMessageBox::Ok);
            }
    
            CloseHandle(handle);
    

    Info:

    1. I get TWizardForm class from Microsoft Spy++ app (TWizardForm class is used by Inno Setup)
    2. Get the window title using GetWindowText method
    3. FindWindowEx now will find the process for the class (TWizardForm) and appropriate window title
    4. Get the process pid using GetWindowThreadProcessId function
    5. Terminate the process
    6. Close the handle

    It will detect the appropriate process and terminate it. I think it's better solution than the previous one.


Log in to reply