2010-10-13 8 views
14

J'ai une application (service Windows) qui est installée dans un répertoire du dossier Program Files. Parallèlement à cette application est une autre application WinForms qui est utilisée pour configurer le service (entre autres choses). Quand il fait la configuration, il enregistre les changements dans un fichier de configuration qui vit à côté du service. Lors de l'exécution de Vista/Win7, l'UAC empêche l'utilisateur d'enregistrer dans le fichier de configuration.Manière correcte de gérer l'UAC en C#

Ce que je voudrais faire est:

  • mettre l'icône de bouclier à côté de l'élément de menu utilisé pour configurer
  • rapide pour les autorisations CCU lorsque cet élément est choisi
  • ne montrent l'icône/invite lorsque sur un OS qui exige
  • afficher uniquement l'icône/rapide lorsque les autorisations sont nécessaires (par exemple. si l'application est installée quelque part qui ne nécessite pas l'autorisation UAC)

Je ne veux pas vraiment pour exécuter l'application entière en tant qu'administrateur, car il est également utilisé à d'autres fins qui ne nécessitent pas d'autorisations UAC (la définition d'un fichier manifeste d'application n'est donc pas la bonne solution). Je suppose également (corrigez-moi si je me trompe) qu'une fois que les autorisations UAC ont été accordées, mon processus existant ne peut pas effectuer l'action et que je vais devoir démarrer un nouveau processus.

Comment puis-je y parvenir au mieux?

+0

Je devais faire un peu de saut à travers les cerceaux pour le coder correctement, mais grâce à Matthew, j'ai quelque chose de similaire à ce que j'ai décrit ci-dessus. – adrianbanks

+0

Bon à entendre. L'UAC fait parfois mal, mais votre logiciel est vraiment meilleur. –

Répondre

21

C'est assez facile. Mettez une icône de bouclier sur le bouton qui enregistre les modifications apportées au fichier de configuration, au lieu de l'élément de menu. Cela suit le comportement de Windows de ne pas demander d'autorisations UAC jusqu'au dernier moment. Le bouton lancera à nouveau votre exécutable en tant qu'administrateur avec une ligne de commande spéciale (que vous décidez) pour effectuer l'enregistrement du fichier de configuration. Utilisez un canal nommé (assurez-vous de lui donner les autorisations correctes) pour transmettre les données de configuration à votre deuxième instance si vous ne souhaitez pas utiliser la ligne de commande pour le transfert de données.

Pour lancer l'exécutable:

ProcessStartInfo info = new ProcessStartInfo(); 
info.FileName = "YOUR EXE"; 
info.UseShellExecute = true; 
info.Verb = "runas"; // Provides Run as Administrator 
info.Arguments = "YOUR SPECIAL COMMAND LINE"; 

if (Process.Start(info) != null) 
{ 
    // The user accepted the UAC prompt. 
} 

Cela fonctionne également lorsque l'UAC n'existe pas (Windows XP), car il suffit de lancer en tant qu'administrateur si possible, ou des informations d'identification invite. Vous pouvez vérifier si le système d'exploitation nécessite UAC en faisant simplement Environment.OSVersion.Version.Major == 6. 6 est à la fois Windows Vista et 7. Vous pouvez vous assurer que vous utilisez Windows en regardant Environment.OSVersion.Platform.

Pour détecter si vous êtes application est déjà admin, vous pouvez le faire:

public static bool IsAdministrator() 
{ 
    WindowsIdentity identity = WindowsIdentity.GetCurrent(); 

    if (identity != null) 
    { 
     WindowsPrincipal principal = new WindowsPrincipal(identity); 
     return principal.IsInRole(WindowsBuiltInRole.Administrator); 
    } 

    return false; 
} 
+0

Vous devriez détecter si l'utilisateur est en cours d'exécution en tant qu'administrateur. Si tel est le cas, vous pouvez souhaiter adopter un comportement différent (par exemple, ne pas lancer une instance distincte et éventuellement omettre l'icône du bouclier). – Brian

+0

@Brian, Comme il l'a souligné, il ne veut pas que toute l'application fonctionne en tant qu'administrateur, donc dans cette situation, il n'y a rien à détecter. Sauf si vous faites référence au compte administrateur réel, où même Windows utilise encore le bouclier. –

+0

@Matthew: Oui, je sais que l'OP ne veut pas que l'application fonctionne en tant qu'administrateur. Cela ne signifie pas que l'utilisateur ne l'exécutera pas en tant qu'administrateur, par exemple. parce que l'utilisateur est sur Windows XP, délibérément utilisé clic droit exécuter en tant qu'administrateur, ou l'utilisateur a désactivé UAC. – Brian

9

Matthew Ferreira's answer va dans les détails sur la raison pour laquelle vous devez redémarrer l'application et tout ce qu'il faut faire quand le redémarrer , cependant il n'a pas couvert comment montrer l'icône de bouclier. Voici un code que j'utilise (je crois que je l'origine ai obtenu d'une autre réponse quelque part sur ce site) qui ne montrera l'icône de bouclier lorsque le programme est pas élevé

/// <summary> 
/// Is a button with the UAC shield 
/// </summary> 
public partial class ElevatedButton : Button 
{ 
    /// <summary> 
    /// The constructor to create the button with a UAC shield if necessary. 
    /// </summary> 
    public ElevatedButton() 
    { 
     FlatStyle = FlatStyle.System; 
     if (!IsElevated()) ShowShield(); 
    } 


    [DllImport("user32.dll")] 
    private static extern IntPtr 
     SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

    private uint BCM_SETSHIELD = 0x0000160C; 

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


    private void ShowShield() 
    { 
     IntPtr wParam = new IntPtr(0); 
     IntPtr lParam = new IntPtr(1); 
     SendMessage(new HandleRef(this, Handle), BCM_SETSHIELD, wParam, lParam); 
    } 
} 

Les contrôles de bouton quand il est en cours de construction si c'est dans un contexte administratif et si ce n'est pas le cas, il dessine l'icône du bouclier sur le bouton.

Si vous souhaitez utiliser l'icône de l'écran de protection, here is a sneaky trick qui renvoie l'icône de protection sous la forme d'un objet Bitmap.

Questions connexes