Come eseguire un’applicazione che richiede diritti di amministratore da uno che non li ha

Sono rimasto bloccato per alcune ore finché non sono finalmente riuscito a farlo. Ci sono già collegamenti che mi hanno indirizzato nella giusta direzione:

  • È ansible che l’eseguibile richieda i diritti di amministratore? (Windows 7)
  • Errore CreateProcess = 740, l’operazione richiesta richiede l’elevazione

Ma ho pensato che una semplice panoramica del problema potesse aiutare qualcuno :).

Problema reale: (da Wikipedia: http://en.wikipedia.org/wiki/User_Account_Control )

Un eseguibile contrassegnato come “requireAdministrator” nel suo manifest non può essere avviato da un processo non elevato utilizzando CreateProcess (). Invece, verrà restituito ERROR_ELEVATION_REQUIRED. È necessario utilizzare ShellExecute () o ShellExecuteEx ().

(Errore BTW, ERROR_ELEVATION_REQUIRED == 740)

Soluzione: (stesso sito)

In un’applicazione nativa Win32 lo stesso verbo “runas” può essere aggiunto a una chiamata ShellExecute () o ShellExecuteEx ().

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

Potrebbe anche essere utile: (fonte: http://mark.koli.ch/2009/12/uac-prompt-from-java-createprocess-error740-the-requested-operation-requires-elevation.html )

2 – Flusso UAC di base

Ok, quindi, prima di approfondire l’argomento, ho pensato che potrebbe essere utile spiegare il stream di base di un’applicazione sensibile al controllo dell’account utente e il modo in cui tutto combacia. Normalmente, l’applicazione viene eseguita come utente non privilegiato. Ma a volte ha bisogno di essere un amministratore (per fare qualsiasi cosa). Quindi, ecco l’idea di base, in pseudo codice:

 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; } 

Finalmente, è così che l’ho fatto:

 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); } 

E solo per completezza: i collegamenti MSDN a ShellExecute e 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