web-dev-qa-db-fra.com

Comment exécuter une application qui nécessite des droits d'administrateur à partir d'une application qui n'en a pas

Je suis resté coincé là-dessus pendant quelques heures jusqu'à ce que j'y parvienne enfin. Il existe déjà des liens qui m'ont indiqué la bonne direction:

Mais j'ai pensé qu'un simple aperçu du problème pourrait aider quelqu'un :).

24
Samuel

Vrai problème: (à partir de Wikipedia: http://en.wikipedia.org/wiki/User_Account_Control )

Un exécutable marqué comme "requireAdministrator" dans son manifeste ne peut pas être démarré à partir d'un processus non élevé à l'aide de CreateProcess (). À la place, ERROR_ELEVATION_REQUIRED sera retourné. ShellExecute () ou ShellExecuteEx () doit être utilisé à la place.

(BTW, erreur ERROR_ELEVATION_REQUIRED == 740)

Solution: (même site)

Dans une application Win32 native, le même verbe "runas" peut être ajouté à un appel ShellExecute () ou ShellExecuteEx ().

ShellExecute(hwnd, "runas", "C:\\Windows\\Notepad.exe", 0, 0, SW_SHOWNORMAL);

Cela peut également être utile: (source: http://mark.koli.ch/2009/12/uac-Prompt-from-Java-createprocess-error740-the-requested-operation-requires-elevation.html )

2 - Flux UAC de base

Ok, donc avant de creuser, j'ai pensé qu'il pourrait être utile d'expliquer le flux de base d'une application compatible UAC et comment tout s'emboîtait. Normalement, votre application s'exécute en tant qu'utilisateur non privilégié. Mais, parfois, il doit être un administrateur (pour faire quoi que ce soit). Voici donc l'idée de base, en pseudo code:

int main (int argc, char **argv) {

  HRESULT operation = tryToDoSomethingPrivileged();

  if (operation == ACCESS_DENIED && !alreadyElevated) {

    // Spawn a copy of ourselves, via ShellExecuteEx().
    // The "runas" verb is important because that's what
    // internally triggers Windows to open up a UAC Prompt.
    HANDLE child = ShellExecuteEx(argc, argv, "runas");

    if (child) {
      // User accepted UAC Prompt (gave permission).
      // The unprivileged parent should wait for
      // the privileged child to finish.
      WaitForSingleObject(child, INFINITE);
      CloseHandle(pid);
    }
    else {
      // User rejected UAC Prompt.
      return FAILURE;
    }

    return SUCCESS;

  }  

  return SUCCESS;

}

Enfin, voici comment je l'ai fait:

if(0 == CreateProcess(argv[2], params, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) {
        //runas Word is a hack to require UAC elevation
        ShellExecute(NULL, "runas", argv[2], params, NULL, SW_SHOWNORMAL);
}

Et juste pour être complet - les liens MSDN vers ShellExecute et CreateProcess:

http://msdn.Microsoft.com/en-us/library/bb762153%28v=vs.85%29.aspx

http://msdn.Microsoft.com/en-us/library/ms682425%28VS.85%29.aspx

30
Samuel