Подтвердить что ты не робот

Как запустить дочерний процесс, который требует повышения и ожидания?

Win 7/UAC сводит меня с ума.

Из моего приложения на С++ мне нужно запустить исполняемый файл, который требует повышения в Windows 7. Я хочу снять эту штуку и дождаться ее завершения, прежде чем продолжить. Какой самый простой способ сделать это?

Обычно я делаю это через CreateProcess(), но он не работает для исполняемых файлов, требующих повышения.

Я попытался работать с использованием cmd.exe /c ... через CreateProcess, который работает, но всплывает уродливое окно терминала cmd.

Я читаю, что ShellExecute() разрешит возвышение, но, похоже, нелегко дождаться окончания exe при использовании ShellExecute(). Будет ли что-то простое, как system() работать?

Любые другие идеи очень ценятся!

4b9b3361

Ответ 1

Используйте ShellExecuteEx, а не ShellExecute. Эта функция предоставит дескриптор созданного процесса, который вы можете использовать для вызова WaitForSingleObject на этом дескрипторе, чтобы до тех пор, пока этот процесс не завершится. Наконец, просто вызовите CloseHandle в дескрипторе процесса, чтобы закрыть его.

Пример кода (большая часть проверки ошибок опущена для ясности и краткости):

SHELLEXECUTEINFO shExInfo = {0};
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = _T("runas");                // Operation to perform
shExInfo.lpFile = _T("C:\\MyApp.exe");       // Application to start    
shExInfo.lpParameters = "";                  // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;  

if (ShellExecuteEx(&shExInfo))
{
    WaitForSingleObject(shExInfo.hProcess, INFINITE);
    CloseHandle(shExInfo.hProcess);
}

Определение глагола "runas" для lpVerb - это то, что заставляет UAC поднимать приложение, которое должно быть запущено. Это эквивалентно настройке уровня разрешений в манифесте приложения на "requireAdministrator". Это потребует повышения UAC как для администратора, так и для ограниченного пользователя.

Но стоит отметить, что, если это абсолютно необходимо, вы должны предпочесть "стандартный" способ добавления манифеста в приложение, которое вы хотите запустить, которое определяет требуемый уровень выполнения. Если вы пройдете этот маршрут, вы просто передадите "open" в качестве lpVerb. Пример манифеста показан ниже:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
        <dependency>
                <dependentAssembly>
                        <assemblyIdentity
                                type="win32"
                                name="Microsoft.Windows.Common-Controls"
                                version="6.0.0.0"
                                processorArchitecture="X86"
                                publicKeyToken="6595b64144ccf1df"
                                language="*"
                        />
                </dependentAssembly>
        </dependency>
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
                <security>
                        <requestedPrivileges>
                                <requestedExecutionLevel 
                                       level="requireAdministrator" 
                                       uiAccess="false"/>
                        </requestedPrivileges>
                </security>
        </trustInfo>
</assembly>

Наконец, убедитесь, что любой элемент в приложении запускает процесс, требующий повышения UAC, помечен соответствующим образом. Это ваша работа, чтобы моделировать это в пользовательском интерфейсе; Windows не обрабатывает его для вас. Это делается путем отображения значка экрана в точке входа; например:

        < t40                                             UAC shield displayed on a menu item

Ответ 2

Что вы можете сделать, так это создать канал для дочернего процесса "stdin" (как если бы вы перенаправляли вход в этот процесс) и дождались, когда труба сломается.

Обратите внимание, что процесс на самом деле не получит перенаправленный вход.

например. если вы попробуете из неэлектированной командной строки сделать

echo help | diskpart

вы увидите возвышение, и окно команд будет ждать, пока вы не закроете отдельное окно.

Ответ 3

Для запуска с повышенными привилегиями требуется, чтобы процесс запуска этого режима был повышен. Для этого обычно требуется безопасный сервис или что-то уже запущенное. Это изменение начинается с Vista. Это связано с тем, что у вас есть полномочия (через токены ACL), чтобы запустить процесс и запустить его с соответствующим уровнем привилегированных унаследованных от запуска процесса. Microsoft прилагает все усилия, чтобы люди создали повышенный процесс, который обрабатывает все повышенные функциональные потребности и оставляет остальных в наименее привилегированном пространстве пользователя. С тех пор как Vista была Alpha. Это боль, но то, как Microsoft предпочла бы, чтобы вы делали что-то по соображениям безопасности.

Кстати, вызов ShellExec не будет работать, если вы запускаете свое приложение из безопасного места, такого как каталог программных файлов, и т.д. Попытались это, прежде чем переходить к модели обслуживания несколько лет назад.

Итак, чтобы запустить ваш процесс и передать UAC, единственный способ сделать это - запустить из процесса, который уже имеет привилегию безопасности для наследования