Élever le privilège de processus par programme?

147

J'essaye d'installer un service utilisant InstallUtil.exe mais invoqué par Process.Start. Voici le code:

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

m_strInstallUtilest le chemin d'accès complet et l'exe vers "InstallUtil.exe" et strExePathest le chemin d'accès complet / nom à mon service.

L'exécution de la syntaxe de ligne de commande à partir d'une invite de commande élevée fonctionne; l'exécution à partir de mon application (en utilisant le code ci-dessus) ne fonctionne pas. Je suppose que je suis confronté à un problème d'élévation de processus, alors comment exécuter mon processus dans un état élevé? Dois-je regarder ShellExecutepour cela?

Tout cela est sous Windows Vista. J'exécute le processus dans le débogueur VS2008 élevé au privilège d'administrateur.

J'ai également essayé le réglage startInfo.Verb = "runas";mais cela ne semblait pas résoudre le problème.

Scott Marlowe
la source
Après avoir ajouté startInfo.UseShellExecute = true;en plus startInfo.Verb = "runas";cela a bien fonctionné pour moi.
Matt le

Réponses:

172

Vous pouvez indiquer que le nouveau processus doit être démarré avec des autorisations élevées en définissant la propriété Verb de votre objet startInfo sur 'runas', comme suit:

startInfo.Verb = "runas";

Cela entraînera le comportement de Windows comme si le processus avait été démarré à partir de l'Explorateur avec la commande de menu "Exécuter en tant qu'administrateur".

Cela signifie que l'invite UAC apparaîtra et devra être reconnue par l'utilisateur: si cela n'est pas souhaitable (par exemple parce que cela se produirait au milieu d'un long processus), vous devrez exécuter l'ensemble de votre processus hôte avec autorisations élevées par Create and Embed an Application Manifest (UAC) pour exiger le niveau d'exécution `` le plus élevé disponible '': cela provoquera l'apparition de l'invite UAC dès le démarrage de votre application et l'exécution de tous les processus enfants avec des autorisations élevées sans invite supplémentaire .

Edit: Je vois que vous venez de modifier votre question pour déclarer que "runas" n'a pas fonctionné pour vous. C'est vraiment étrange, comme il se doit (et c'est le cas pour moi dans plusieurs applications de production). Exiger que le processus parent s'exécute avec des droits élevés en incorporant le manifeste devrait cependant fonctionner.

mdb
la source
9
"runas" ne fonctionnait pas non plus pour moi. Peut-être que cela ne fonctionne que lorsque l'UAC est désactivé?
Dirk Vollmar
18
@LukePuplett Je les remercie. C'est un excellent moyen d'atténuer l'installation du kit racine sans séparer complètement les rôles utilisateur.
Colton
6
@Sparksis, mais il y a aussi un autre point de vue. Les gens qui savent défendre leur OS, ils savent comment le faire sans UAC. Et les utilisateurs factices, qui ne savent pas ce qu'est la défense, cliquent sur «OUI» à chaque fois qu'ils voient la fenêtre UAC. De plus, rien ne peut empêcher les mauvais-hackers-virus-writers d'utiliser des exploits pour le contourner;) Donc je suis d'accord avec LukePuplett =)
Jet
24
Il semble que vous deviez également définir startInfo.ShellExecute=truepour que cela fonctionne ... aussi je n'ai pas pu faire fonctionner cette méthode avec des fichiers exécutables qui se trouvent sur un partage réseau (je dois les copier dans le répertoire temporaire local avant de l'exécuter). ..
TCC
7
@Jet Désolé mais c'est le mauvais état d'esprit. Chaque fois qu'une boîte de dialogue UAC est affichée pendant l'installation, c'est un échec du système. Là où cela a de la valeur, c'est lorsque vous voyez une boîte UAC sans exécuter quelque chose nécessitant une élévation. Peu importe à quel point vous - n'importe lequel d'entre nous - pensez que nous sommes sur nos PC, vous ne pouvez pas par magie bloquer zéro jour / téléchargement au volant (par exemple un récent sur le site officiel du prix Nobel). Si vous accédez à ce site et que vous recevez une invite UAC, vous saurez qu'il y a eu un problème. Avec l'UAC désactivé, vous ne saurez jamais que vous venez de rejoindre un botnet. Le coût de l'avertissement préalable est de devoir cliquer sur Oui de temps en temps
base
46

Ce code rassemble tout ce qui précède et redémarre l'application wpf actuelle avec les privilèges d'administrateur:

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)

Mise à jour: la méthode du manifeste d'application est préférée:

Cliquez avec le bouton droit de la souris sur le projet dans Visual Studio, ajoutez un nouveau fichier manifeste d'application, modifiez le fichier afin que vous ayez défini requireAdministrator comme indiqué ci-dessus.

Un problème avec la méthode d'origine: si vous mettez le code de redémarrage dans app.xaml.cs OnStartup, il peut toujours démarrer brièvement la fenêtre principale même si Shutdown a été appelé. Ma fenêtre principale a explosé si app.xaml.cs init n'était pas exécuté et dans certaines conditions de course, il le ferait.

Curtis Yallop
la source
Voir ci-dessous pour les améliorations.
JCCyC
requireAdministrator n'a pas fonctionné dans mon cas. Je devais donc le faire à votre façon. Cela a résolu mon problème! Merci. Mais j'ai dû définir l'application d'instance unique sur false.
chris
Cela a fonctionné pour moi. J'ai également passé l'original string[] argsau processus réapparu.
DotNetPadawan
7
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

Cela le fera sans UAC - pas besoin de démarrer un nouveau processus. Si l'utilisateur en cours d'exécution est membre du groupe Admin comme pour mon cas.

hB0
la source
3
En utilisant ce code, j'obtiens une erreur d'autorisation: "La demande d'autorisation d'entité de sécurité a échoué." :(
Leonardo
Peut-être "Si l'utilisateur en cours d'exécution est membre de Admin" *
hB0
1
intéressant - cela peut aller sur n'importe quelle méthode, pas seulement une méthode d'action (je l'ai même essayé sur une méthode définie dans une page ASPX)
Simon_Weaver
1

Vous devez utiliser l'emprunt d'identité pour élever l'état.

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

N'oubliez pas d'annuler le contexte imité lorsque vous avez terminé.

Vijesh VP
la source
28
Vous n'avez pas dit comment obtenir le accessToken. LogonUser fournira le contexte de sécurité restreint d'un utilisateur lorsque l'UAC est activé.
cwa
Si vous utilisez VSTS, vous pouvez obtenir un jeton d'accès personnel à partir des paramètres du portail Web. (Recherchez l'icône des paramètres à côté de l'image de l'utilisateur.) MSDocs
Su Llewellyn