web-dev-qa-db-fra.com

Comment élever des privilèges uniquement en cas de besoin?

Cette question s'applique à Windows Vista!

J'ai une application qui fonctionne normalement sans privilèges administratifs. Il y a une activité qui a besoin de privilèges administratifs mais je ne veux pas démarrer l'application elle-même avec des privilèges plus élevés quand je sais que la plupart du temps, l'utilisateur n'utilisera même pas cette fonctionnalité.

Je pense à une certaine méthode par laquelle je peux élever les privilèges d'application sur un événement (comme appuyer sur un bouton). Exemple:

Si l'utilisateur clique sur ce bouton, il est invité avec une boîte de dialogue UAC ou un consentement. Comment puis-je faire ceci?

82
Hemant

Je ne pense pas qu'il soit possible d'élever le processus en cours d'exécution. Il est intégré à Windows Vista que les privilèges d'administrateur sont accordés à un processus au démarrage, si je comprends bien. Si vous regardez différents programmes qui utilisent l'UAC, vous devriez voir qu'ils lancent en fait un processus distinct chaque fois qu'une action administrative doit être effectuée (le Gestionnaire des tâches en est un, Paint.NET en est un autre, ce dernier étant en fait une application .NET ).

La solution typique à ce problème consiste à spécifier des arguments de ligne de commande lors du lancement d'un processus élevé (la suggestion d'Abatishchev est une façon de le faire), de sorte que le processus lancé ne sache que pour afficher une certaine boîte de dialogue, puis quittez après que cette action ait été terminé. Ainsi, il ne devrait pas être perceptible à l'utilisateur qu'un nouveau processus ait été lancé puis quitté, et qu'il préfère apparaître comme si une nouvelle boîte de dialogue au sein de la même application avait été ouverte (surtout si vous avez du piratage pour faire la fenêtre principale de la processus élevé un enfant du processus parent). Si vous n'avez pas besoin d'interface utilisateur pour l'accès élevé, c'est encore mieux.

Pour une discussion complète de l'UAC sur Vista, je vous recommande de voir cet article très complet sur le sujet (les exemples de code sont en C++, mais je pense que vous devrez utiliser WinAPI et P/Invoke pour faire la plupart des choses en C # de toute façon). J'espère que vous voyez maintenant au moins la bonne approche à adopter, bien que la conception d'un programme compatible UAC soit loin d'être triviale ...

56
Noldorin

Comme il a été dit :

Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";

exécutera le processus en tant qu'administrateur pour faire tout ce dont vous avez besoin avec le registre, mais revenez à votre application avec les privilèges normaux.

15
abatishchev

L'article 981778 de la base de connaissances MSDN suivant décrit comment "élever automatiquement" une application:

http://support.Microsoft.com/kb/981778

Il contient des exemples téléchargeables en Visual C++, Visual C #, Visual Basic.NET.

Cette approche contourne la nécessité de démarrer un processus distinct, mais en fait, c'est l'application d'origine qui est redémarrée, s'exécutant en tant qu'utilisateur élevé. Néanmoins, cela peut toujours être très utile dans certains contextes où il n'est pas pratique de dupliquer du code dans un exécutable séparé.

Pour supprimer l'élévation, vous devez quitter l'application.

13
FruitBreak

Vous avez besoin d'un moniker UAC et du code pour exécuter elevated en tant qu'objet COM.

Voir cette question.

Documentation sur MSDN.

4
Richard

Peut-être que quelqu'un est utile dans cet exemple simple:

using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Security.Principal;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    internal static class Program
    {
        private class Form1 : Form
        {
            internal Form1()
            {
                var button = new Button{ Dock = DockStyle.Fill };
                button.Click += (sender, args) => RunAsAdmin();
                Controls.Add(button);

                ElevatedAction();
            }
        }

        [STAThread]
        internal static void Main(string[] arguments)
        {
            if (arguments?.Contains("/run_elevated_action") == true)
            {
                ElevatedAction();
                return;
            }

            Application.Run(new Form1());
        }

        private static void RunAsAdmin()
        {
            var path = Assembly.GetExecutingAssembly().Location;
            using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action")
            {
                Verb = "runas"
            }))
            {
                process?.WaitForExit();
            }
        }

        private static void ElevatedAction()
        {
            MessageBox.Show($@"IsElevated: {IsElevated()}");
        }

        private static bool IsElevated()
        {
            using (var identity = WindowsIdentity.GetCurrent())
            {
                var principal = new WindowsPrincipal(identity);

                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

    }
}
2
Konstantin S.

Je sais que c'est un vieux post, mais c'est en réponse à quelqu'un d'autre qui tombe sur la suggestion de MarcP. Le message msdn auquel il a fait référence redémarre en effet les applications dans tous les exemples de code. Les exemples de code utilisent le verbe runas déjà proposé dans d'autres suggestions.

J'ai téléchargé le code pour m'assurer, mais cela provient de l'article msdn d'origine:

4. Cliquez sur Oui pour approuver l'élévation. Ensuite, l'application d'origine redémarre, s'exécutant en tant qu'administrateur élevé.
5. Fermez l'application.

1
SpaceGhost440