Родос обещает "develop-once-run-everywhere" решение. Не судили их самостоятельно.
Создайте объект задания с помощью CreateJobObject
. Используйте CreateProcess
, чтобы запустить UninstallA.exe
в приостановленном состоянии. Назначьте этот новый процесс своему объекту задания с помощью AssignProcessToJobObject
. Запустите UninstallA.exe, вызвав ResumeThread
для дескриптора потока, полученного вами из CreateProcess
.
Затем самая сложная часть: дождитесь, пока объект задания завершит свое выполнение. К сожалению, это немного сложнее, чем можно было бы обоснованно надеяться. Основная идея состоит в том, что вы создаете порт завершения ввода-вывода, затем вы создаете объект объекта, связываете его с портом завершения ввода-вывода и, наконец, ожидаете порта завершения ввода-вывода (получая его статус с помощью GetQueuedCompletionStatus
). У Раймонда Чена есть демонстрация (и объяснение того, как это произошло) в его блоге .
Есть не общий способ дождаться всех внуков, но для вашего конкретного случая вы можете что-то взломать вместе. Вы знаете, что ищете конкретный экземпляр процесса. Сначала я бы дождался выхода uninstallA.exe (используя WaitForSingleObject), потому что в этот момент вы знаете, что uninstallB.exe запущен. Затем используйте EnumProcesses и GetProcessImageFileName из PSAPI, чтобы найти работающий экземпляр uninstallB.exe. Если вы не найдете его, значит, он уже закончен, в противном случае вы можете подождать.
Дополнительная сложность заключается в том, что если вам нужно поддерживать версии Windows старше XP, вы не можете использовать GetProcessImageFileName, а для Windows NT вообще нельзя использовать PSAPI. Для Windows 2000 вы можете использовать GetModuleFileNameEx, но у него есть некоторые предостережения, которые означают, что иногда он может давать сбой (проверьте документацию). Если вам необходимо поддерживать NT, найдите Toolhelp32.
Да, это очень уродливо.
Одна из возможностей - установить Cygwin, а затем использовать команду ps, чтобы следить за выходом внучки