簡體   English   中英

我如何等待由我的應用程序Qt / C ++啟動的另一個應用程序啟動的應用程序

[英]How can I wait for an application launched by another application launched by my application Qt/C++

我正在Qt 5.4中創建一個Windows“添加/刪除程序”應用程序,而我正瘋狂地解決了一些“難題”:

我的應用程序(APP_0)運行另一個應用程序(APP_1)​​,並等待此APP_1終止。

APP_1是一個卸載程序(即,uninstall.exe),我不是我的Qt APP_0的APP_1的源代碼。

APP_1而不是執行卸載工作,它只是將自身復制到文件系統中的某個位置(我看到為Au_.exe,但其他應用程序可以使用不同的名稱和位置),運行其自身的副本(APP_2)並終止。

APP_2具有GUI,正在運行的APP_2的最終用戶需要我正在等待的任務(卸載)。

在這種情況下,我的應用程序(APP_0)會立即停止等待APP_1(因為它啟動了APP_1並等待APP_1)​​。 但是顯然,要正常工作,我需要知道APP_2何時終止...

因此,問題是:是否有一種方法(使用某些技術(掛鈎)?)來知道APP_2是否以及何時終止?

注意:請考慮使用標准的Windows添加/刪除程序實用程序成功完成了該作業(似乎正在等待APP_2)。 您可以對此進行測試,例如,安裝Adobe Digital Edition。 其卸載程序(uninstall.exe)將自身作為Au_.exe復制到User_Local_Temp文件夾中的新文件夾中,然后運行它並終止。 但是OS實用程序成功等待Au_.exe,並且只有在終止后才會刷新已安裝程序的列表。

如果這種技術(uninstall.exe始終將其自身復制到具有相同名稱(Au_.exe)的某處),則可以很簡單地解決此問題。 但是我不認為復制的卸載程序的名稱總是相同的,而且我也不喜歡假設不確定的事情是真實的。

提前謝謝了

感謝IInspectable的建議(請參閱他的評論……非常感謝!),我創建了一個解決我的問題的函數! 我將在這里分享此功能,該功能可能對其他遇到相同(或相似)問題的人有用。

對於我的需求,該函數從QList接收要卸載的項目的索引作為參數,並獲取卸載字符串(例如:C:\\ ProgramFiles \\ MyApp \\ uninstall.exe)。

然后,使用此卸載字符串,我將創建一個進程(CreateProcess)並將其句柄放入作業對象,以便我的函數將等待該進程運行的所有進程。

該函數本身非常簡單,可以改進。 請注意,必須使用CREATE_BREAKAWAY_FROM_JOB選項創建該進程,否則,AssignProcessToJobObject將失敗,並顯示“訪問被拒絕”錯誤。

void MainWindow::uniButtonClick(int idx)
{
    QMessageBox::StandardButton reply;
    QMessageBox::StandardButton err;

    reply = QMessageBox::question(this, "Uninstall/Change", "Uninstall " +
                                  ip[idx].displayName +"?\r\n\r\n" + ip[idx].uninstallString,
                                  QMessageBox::Yes|QMessageBox::No);
    if (reply == QMessageBox::Yes)
    {
        //QString s = "C:\\windows\\notepad.exe"; // Just to test Job assignment and createprocess
        QString s = ip[idx].uninstallString; // the real uninstaller string

        QString jobName = "MyJobObject";

        try
        {
            PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
            STARTUPINFO StartupInfo; //This is an [in] parameter
            PJOBOBJECT_BASIC_PROCESS_ID_LIST pList;
            HANDLE hProcess;
            BOOL bJobAllEnd;



            ZeroMemory(&StartupInfo, sizeof(StartupInfo));
            StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field

            wchar_t* path;
            path = (wchar_t*) malloc (sizeof(wchar_t)*s.length()+1);
            s.toWCharArray(path);
            path[s.length()]=0; // Null terminate the string

            // Create the process with CREATE_BREAKAWAY_FROM_JOB to overcome the AccessDenied issue on AssignProcessToJobObject.
            if(CreateProcess(NULL, path, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB|CREATE_SUSPENDED, NULL, NULL,&StartupInfo, &ProcessInfo))
            {
                pList = (PJOBOBJECT_BASIC_PROCESS_ID_LIST)GlobalAlloc(GMEM_FIXED, 10000);

                HANDLE jobObj = CreateJobObject(NULL, (const wchar_t*)jobName.utf16());

                if (AssignProcessToJobObject(jobObj, ProcessInfo.hProcess) != 0)
                {
                    ResumeThread(ProcessInfo.hThread); // Process assigned to JobObjext, resume it now

                    do
                    {
                        QueryInformationJobObject(jobObj, JobObjectBasicProcessIdList, pList, 10000, NULL);

                        bJobAllEnd = TRUE;

                        for(DWORD i=0; i<pList->NumberOfProcessIdsInList; i++)
                        {
                            hProcess = OpenProcess(SYNCHRONIZE, FALSE, pList->ProcessIdList[i]);
                            if(hProcess != NULL)
                            {
                                CloseHandle(hProcess);
                                bJobAllEnd = FALSE;
                            }
                        }

                        Sleep(500);
                    } while(!bJobAllEnd);


                }
                else
                    qDebug() << "AssignProcess to Job failed: error = " << QString::number(GetLastError());

                GlobalFree(pList);
                CloseHandle(jobObj);
                CloseHandle(ProcessInfo.hThread);
                CloseHandle(ProcessInfo.hProcess);
            }

        }
        catch(QString error)
        {
          QMessageBox::critical(this, "File not found!", "The requested uninstaller doesn't exists", QMessageBox::Ok);

        }


        // refresh list
        handleButton();

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM