[英]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.