2010-10-13 11 views
14

Ich habe eine Anwendung (Windows-Dienst), die in einem Verzeichnis im Ordner Programme installiert ist. Neben dieser Anwendung befindet sich eine weitere WinForms-Anwendung, mit der (unter anderem) der Dienst konfiguriert wird. Wenn es konfiguriert wird, speichert es Änderungen an einer Konfigurationsdatei, die sich neben dem Dienst befindet.Richtiger Weg zum Umgang mit UAC in C#

Bei Ausführung unter Vista/Win7 verhindert UAC, dass der Benutzer in die Konfigurationsdatei speichern kann. Was ich möchte, ist tun:

  • legte das Schild-Symbol neben dem Menüpunkt
  • Aufforderung für UAC-Berechtigungen konfigurieren, wenn dieser Artikel zeigen gewählt
  • nur das Symbol/prompt, wenn sie auf eine Betriebssystem, das erfordert (irgendwo installiert ist z. B., wenn die Anwendung, die nicht UAC Erlaubnis erforderlich ist) es
  • nur zeigt das Symbol/Eingabeaufforderung, wenn Berechtigungen erforderlich sind

ich nicht wirklich die gesamte Anwendung ausgeführt werden soll als Administrator, da er auch für andere Zwecke verwendet wird, für die keine UAC-Berechtigungen erforderlich sind (daher ist das Festlegen einer Anwendungsmanifestdatei nicht die richtige Lösung). Ich nehme auch an (korrigiere mich, wenn ich falsch liege), dass, sobald UAC-Berechtigungen gewährt wurden, mein existierender Prozess die Aktion nicht ausführen kann und dass ich einen neuen Prozess starten muss.

Wie kann ich das am besten erreichen?

+0

Ich musste ein bisschen durch die Ringe springen, um das richtig zu programmieren, aber dank Matthew habe ich etwas, was ich oben beschrieben habe. – adrianbanks

+0

Gut zu hören. UAC macht manchmal Probleme, aber deine Software ist wirklich besser dafür. –

Antwort

21

Das ist ziemlich einfach. Setzen Sie ein Schildsymbol auf die Schaltfläche, die Änderungen an der Konfigurationsdatei anstelle des Menüelements speichert. Dies folgt dem Windows-Verhalten, UAC-Berechtigungen bis zum letzten Moment nicht anzufordern. Die Schaltfläche startet Ihre ausführbare Datei als Administrator mit einer speziellen Befehlszeile (die Sie entscheiden), um die Konfigurationsdatei zu speichern. Verwenden Sie eine Named Pipe (stellen Sie sicher, dass Sie die richtigen Berechtigungen haben), um die Konfigurationsdaten an Ihre zweite Instanz zu übergeben, wenn Sie die Befehlszeile nicht für die Datenübergabe verwenden möchten.

Für die ausführbare Datei starten:

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

Dies funktioniert auch, wenn UAC existiert nicht (Windows XP), weil es einfach als Administrator, wenn möglich ausgeführt werden, oder für Anmeldeinformationen aufgefordert. Sie können überprüfen, ob das Betriebssystem UAC benötigt, indem Sie einfach Environment.OSVersion.Version.Major == 6 ausführen. 6 ist sowohl Windows Vista als auch 7. Sie können sicherstellen, dass Sie Windows verwenden, indem Sie Environment.OSVersion.Platform betrachten.

Zur Erkennung, ob Sie bereits Anwendung Admin ist, können Sie dies tun:

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

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

    return false; 
} 
+0

Sie sollten feststellen, ob der Benutzer derzeit als Administrator ausgeführt wird. Wenn dies der Fall ist, möchten Sie sich möglicherweise anders verhalten (z. B. keine separate Instanz starten und möglicherweise das Schildsymbol weglassen). – Brian

+0

@Brian, Wie er darauf hinwies, möchte er nicht, dass die ganze Anwendung als admin läuft, also gibt es in dieser Situation nichts zu entdecken. Es sei denn, Sie beziehen sich auf das eigentliche Administratorkonto, wo sogar Windows das Schild verwendet. –

+0

@Matthew: Ja, ich weiß, dass das OP nicht möchte, dass die App als Admin läuft. Das bedeutet nicht, dass der Benutzer es nicht als Administrator ausführen wird, z. Da der Benutzer unter Windows XP ist, wird er absichtlich mit der rechten Maustaste als Administrator ausgeführt, oder der Benutzer hat die Benutzerkontensteuerung deaktiviert. – Brian

9

Matthew Ferreira's answer geht in den Details, warum müssen Sie die gesamte Anwendung neu zu starten und was zu tun ist, wenn es neu zu starten , aber er hat nicht behandelt, wie man das Schildsymbol zeigt. Hier ist ein Code verwende ich (ich glaube, ich habe es ursprünglich aus einer anderen Antwort irgendwo auf dieser Seite), die nur das Schild-Symbol zeigen, wenn das Programm nicht

erhöht ist
/// <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); 
    } 
} 

Die Schaltfläche überprüft, wenn es so konstruiert ist, wenn Es ist in einem administrativen Kontext und wenn es nicht ist, zeichnet es das Schildsymbol auf dem Knopf.

Wenn Sie möchten, dass das Schildsymbolfenster here is a sneaky trick verwendet, wird das Schildsymbol als Bitmap Objekt zurückgegeben.

Verwandte Themen