Elevare i privilegi di processo a livello di codice?


147

Sto cercando di installare un servizio utilizzando InstallUtil.exe ma invocato tramite Process.Start. Ecco il codice:

ProcessStartInfo startInfo = new ProcessStartInfo (m_strInstallUtil, strExePath);
System.Diagnostics.Process.Start (startInfo);

dove si m_strInstallUtiltrova il percorso completo ed exe in "InstallUtil.exe" ed strExePathè il percorso / nome completo per il mio servizio.

L'esecuzione della sintassi della riga di comando da un prompt dei comandi con privilegi elevati funziona; in esecuzione dalla mia app (utilizzando il codice sopra) no. Suppongo di aver a che fare con un problema di elevazione del processo, quindi come eseguirò il processo in uno stato elevato? Devo cercarlo ShellExecute?

Questo è tutto su Windows Vista. Sto eseguendo il processo nel debugger VS2008 elevato al privilegio di amministratore.

Ho anche provato a impostare startInfo.Verb = "runas";ma non sembra risolvere il problema.


Dopo aver aggiunto, startInfo.UseShellExecute = true;inoltre, startInfo.Verb = "runas";ha funzionato bene per me.
Matt

Risposte:


172

Puoi indicare che il nuovo processo dovrebbe essere avviato con autorizzazioni elevate impostando la proprietà Verb dell'oggetto startInfo su 'runas', come segue:

startInfo.Verb = "runas";

Ciò farà sì che Windows si comporti come se il processo fosse stato avviato da Explorer con il comando di menu "Esegui come amministratore".

Ciò significa che il prompt UAC verrà visualizzato e dovrà essere riconosciuto dall'utente: se questo non è desiderabile (ad esempio perché si verificherebbe nel mezzo di un lungo processo), dovrai eseguire l'intero processo host con autorizzazioni elevate di Crea e incorpora un manifest di applicazione (UAC) per richiedere il livello di esecuzione "massima disponibile": questo farà apparire il prompt UAC non appena viene avviata l'app e tutti i processi figlio verranno eseguiti con autorizzazioni elevate senza ulteriori prompt .

Modifica: Vedo che hai appena modificato la tua domanda per affermare che "runas" non ha funzionato per te. È davvero strano, come dovrebbe (e lo fa per me in diverse app di produzione). Tuttavia, è necessario che il processo genitore venga eseguito con diritti elevati incorporando manifest.


9
"Runas" non ha funzionato neanche per me. Potrebbe essere che funziona solo con UAC disattivato?
Dirk Vollmar,

18
@LukePuplett Li ringrazierei. È un ottimo modo per mitigare l'installazione del root-kit senza separare completamente i ruoli utente.
Colton

6
@Sparksis, ma c'è anche un altro punto di vista. Le persone che sanno come difendere il proprio sistema operativo, sanno come farlo senza controllo dell'account utente. E gli utenti fittizi, che non sanno cosa sia la difesa, fanno clic su "SÌ" ogni volta che visualizzano la finestra Controllo dell'account utente. Inoltre, nulla può impedire agli autori di virus e hacker di utilizzare gli exploit per aggirarlo;) Quindi sono d'accordo con LukePuplett =)
Jet

24
Sembra che tu debba anche impostare startInfo.ShellExecute=truequesto per funzionare ... inoltre non sono stato in grado di far funzionare questo metodo con file eseguibili che si trovano su una condivisione di rete (devi copiarli nella directory temp locale prima di eseguire). ..
TCC,

7
@Jet Siamo spiacenti ma questa è la mentalità sbagliata. Ogni volta che viene visualizzata una finestra di dialogo Controllo dell'account utente durante l'installazione, si verifica un errore del sistema. Dove è prezioso è quando vedi una casella UAC senza eseguire qualcosa che richiede elevazione. Non importa quanto tu, nessuno di noi, pensi di essere sui nostri PC, non puoi bloccare magicamente zero giorni / download drive-by (ad es. Uno recente sul sito ufficiale del Premio Nobel). Se navighi su quel sito e ricevi un prompt UAC, sapresti che c'era qualcosa che non andava. Con UAC disattivato, non sapresti mai di essere appena entrato in una botnet. Il costo dell'avviso anticipato deve fare clic su Sì di tanto in tanto
Base

46

Questo codice mette insieme soprattutto e riavvia l'attuale app wpf con i privilegi di amministratore:

if (IsAdministrator() == false)
{
    // Restart program and run as admin
    var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
    Application.Current.Shutdown();
    return;
}

private static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}


// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)

Aggiornamento: si preferisce il modo manifest app:

Fare clic con il tasto destro del mouse su Visual Studio, aggiungere, nuovo file manifest dell'applicazione, modificare il file in modo da avere impostato l'Amministratore come mostrato sopra.

Un problema con il modo originale: se inserisci il codice di riavvio in app.xaml.cs OnStartup, potrebbe comunque avviare brevemente la finestra principale anche se è stato chiamato Shutdown. La mia finestra principale è esplosa se app.xaml.cs init non è stato eseguito e in determinate condizioni di gara lo farebbe.


Vedi sotto per miglioramenti.
JCCyC,

Requisito amministrativo non ha funzionato nel mio caso. Quindi ho dovuto farlo a modo tuo. Questo ha risolto il mio problema! grazie. Ma ho dovuto impostare l'applicazione Single Instance su false.
chris,

Questo ha funzionato per me. Ho anche passato l'originale string[] argsal processo di rigenerazione.
DotNetPadawan,


7
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

Questo lo farà senza UAC - non è necessario avviare un nuovo processo. Se l'utente in esecuzione è membro del gruppo Admin come nel mio caso.


3
Utilizzando questo codice viene visualizzato un errore di autorizzazione: "Richiesta di autorizzazione dell'entità di sicurezza non riuscita." :(
Leonardo,

Forse "Se l'utente corrente è membro dell'amministratore" *
hB0

1
interessante - questo può andare su qualsiasi metodo, non solo su un metodo di azione (l'ho anche provato su un metodo definito in una pagina ASPX)
Simon_Weaver

1

È necessario utilizzare la rappresentazione per elevare lo stato.

WindowsIdentity identity = new WindowsIdentity(accessToken);
WindowsImpersonationContext context = identity.Impersonate();

Non dimenticare di annullare il contesto impersonato quando hai finito.


28
Non hai detto come ottenere l'accesso. LogonUser fornirà un contesto di sicurezza limitato dell'utente quando UAC è abilitato.
cwa,

Se si utilizza VSTS, è possibile ottenere un token di accesso personale dalle Impostazioni nel portale Web. (Cerca l'icona delle impostazioni accanto all'immagine dell'utente.) MSDocs
Su Llewellyn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.