Как я могу попросить пользователя о повышенных разрешениях во время выполнения? - PullRequest
6 голосов
/ 24 мая 2011

Некоторые приложения, запущенные с обычным пользователем, при необходимости запрашивают повышенные разрешения (например, файловый менеджер должен написать такую ​​папку), а затем продолжают операцию.

Как я могу повторить это поведение?

Ответы [ 4 ]

4 голосов
/ 26 мая 2011

Как отметил Тамас, вам нужно запустить новый процесс с повышенными правами.В прошлом я много искал, но не нашел способа повысить права текущего процесса.

Допустим, ваше основное приложение - App1.exe, а затем вы вызываете вторичный процесс App2.exe, для которого требуетсяповышенные права.


A.Вы можете встроить манифест в свой App2.exe, но более простой способ - создать файл манифеста [текстовый файл] с именем App2.exe.manifest со следующим содержимым и поместить его в тот же каталог, что и App2.exe. Заметка: !!Как ни странно, если имя вашего приложения не App2.exe, а App2_install.exe или App2_setup.exe (т. Е. Если имя приложения содержит «install» или «setup»), диалоговое окно UAC автоматически появится в Windows Vista / Windows 7и будет просить о повышенных правах, даже если нет файла манифеста!Это образец файла манифеста:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

B.Вы можете использовать код, подобный следующему в App1.exe, чтобы запустить App2.exe

QString AppToExec = qApp->applicationDirPath() + "/App2.exe";
// Put any required parameters of App2.exe to AppParams string
QString AppParams = "";
if (0 != genWin32ShellExecute(AppToExec, 
                              "",    // default verb: "open" or "exec"
                              AppParams,
                              false, // run hidden
                              true)) // wait to finish
{
    // (...) handle error
}

... и, наконец, это код функции Win32 genWin32ShellExecute (), которую я создал длязапустить процесс или открыть документ при использовании QT на Win32 O / S:

Заголовок:

#ifdef Q_OS_WIN  // Implement genWin32ShellExecute() especially for UAC
    #include "qt_windows.h"
    #include "qwindowdefs_win.h"
    #include <shellapi.h>

int genWin32ShellExecute(QString AppFullPath,
                         QString Verb,
                         QString Params,
                         bool ShowAppWindow,
                         bool WaitToFinish);
#endif

CPP:

// Execute/Open the specified Application/Document with the given command
// line Parameters
// (if WaitToFinish == true, wait for the spawn process to finish)
//
// Verb parameter values:
// ""           The degault verb for the associated AppFullPath
// "edit"       Launches an editor and opens the document for editing.
// "find"       Initiates a search starting from the specified directory.
// "open"       Launches an application. If this file is not an executable file, its associated application is launched.
// "print"      Prints the document file.
// "properties" Displays the object's properties.
//
// Ret: 0 = success
//     <0 = error
#ifdef Q_OS_WIN
int genWin32ShellExecute(QString AppFullPath,
                         QString Verb,
                         QString Params,
                         bool ShowAppWindow,
                         bool WaitToFinish)
{
    int Result = 0;

    // Setup the required structure
    SHELLEXECUTEINFO ShExecInfo;
    memset(&ShExecInfo, 0, sizeof(SHELLEXECUTEINFO));
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = NULL;
    if (Verb.length() > 0)
        ShExecInfo.lpVerb = reinterpret_cast<const WCHAR *>(Verb.utf16());
    ShExecInfo.lpFile = NULL;
    if (AppFullPath.length() > 0)
        ShExecInfo.lpFile = reinterpret_cast<const WCHAR *>(AppFullPath.utf16());
    ShExecInfo.lpParameters = NULL;
    if (Params.length() > 0)
        ShExecInfo.lpParameters = reinterpret_cast<const WCHAR *>(Params.utf16());
    ShExecInfo.lpDirectory = NULL;
    ShExecInfo.nShow = (ShowAppWindow ? SW_SHOW : SW_HIDE);
    ShExecInfo.hInstApp = NULL;

    // Spawn the process
    if (ShellExecuteEx(&ShExecInfo) == FALSE)
    {
        Result = -1; // Failed to execute process
    } else if (WaitToFinish)
    {
        WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
    }

    return Result;
}
#endif
3 голосов
/ 24 мая 2011

См. этот вопрос о повышении привилегий, только когда это требуется в C # и , в этой статье о контроле учетных записей

Подводя итог: нужно запустить новый процесс с повышенными правами доступа. Уровень возвышения не может быть изменен во время выполнения. Запуск с повышенными правами выполняется либо через WinAPI, либо встраивания правильного манифеста в исполняемый файл.

2 голосов
/ 24 мая 2011

Вы также можете запустить COM-объект в режиме повышенных прав. См. Эту статью MSDN для получения дополнительной информации.

2 голосов
/ 24 мая 2011

В двух словах: создайте два исполняемых файла для Windows.Обычный исполняемый файл и рабочий исполняемый файл, который вы используете для выполнения «повышенных» операций (путем передачи параметров командной строки).

Во второй EXE-файл вы добавляете файл манифеста приложения с <requestExecutionLevel level="requireAdministrator"/> узел.

При запуске рабочего приложения обязательно используйте функцию QT, которая обертывает ShellExecute, НЕ CreateProcess, поскольку CreateProcess просто не может запустить приложения requireAdministrator, тогда как ShellExecute (будучи функцией оболочки) может выполнятьзапрос на повышение прав UAC.

Это также возможно сделать с помощью элементов управления ActiveX, но поскольку вы нацеливаетесь на Qt, это кажется менее подходящим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...