2010-10-13 14 views
14

Mam aplikacji (usługa systemu Windows), który jest zainstalowany w katalogu w folderze Program Files. Oprócz tej aplikacji jest kolejną aplikacją WinForms, która służy do konfigurowania usługi (między innymi). Kiedy wykonuje konfigurację, zapisuje zmiany w pliku konfiguracyjnym, który funkcjonuje wraz z usługą.Prawidłowy sposób postępowania z UAC w języku C#

Podczas uruchamiania w systemie Vista/Win7 UAC uniemożliwia użytkownikowi zapisywanie do pliku konfiguracyjnego. Co chciałbym zrobić, to:

  • umieścić ikonę tarczy obok pozycji menu używane do konfigurowania
  • monit o uprawnieniach UAC, kiedy ta pozycja jest wybrana
  • pokazać tylko ikona/szybka kiedy na zasadzie OS że wymaga
  • tylko pokazać się ikona/szybka kiedy wymagane są uprawnienia (np. jeśli aplikacja jest zainstalowana gdzieś, że nie wymaga zgody UAC)

ja naprawdę nie chce uruchomić całą aplikację jako administrator, ponieważ jest również używany do innych celów, które nie wymagają uprawnień UAC (więc ustawienie pliku manifestu aplikacji nie jest poprawnym rozwiązaniem). Zakładam też (popraw mnie, jeśli się mylę), że gdy uprawnienia UAC zostaną przyznane, mój istniejący proces nie będzie mógł wykonać akcji i będę musiał rozpocząć nowy proces.

Jak najlepiej to osiągnąć?

+0

Musiałem trochę przeskoczyć przez obręcze, żeby to poprawnie zakodować, ale dzięki Mateuszowi mam coś podobnego do tego, co opisałem powyżej. – adrianbanks

+0

Dobrze słyszeć. UAC czasami sprawia ból, ale twoje oprogramowanie jest naprawdę lepsze. –

Odpowiedz

21

To dość łatwe. Umieść ikonę tarczy na przycisku, która zapisuje zmiany w pliku konfiguracyjnym, zamiast pozycji menu. Wynika to z zachowania systemu Windows polegającego na tym, że nie żąda się uprawnień UAC do ostatniej chwili. Przycisk rzeczywiście uruchomi twój plik wykonywalny ponownie jako administrator ze specjalnym wierszem poleceń (który zdecydujesz), aby zapisać plik konfiguracji. Użyj nazwanego potoku (upewnij się, że nadałeś mu odpowiednie uprawnienia), aby przekazać dane konfiguracyjne do twojej drugiej instancji, jeśli nie chcesz używać wiersza poleceń do przekazywania danych.

do uruchomienia pliku wykonywalnego:

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

Działa to także wtedy, gdy nie istnieje UAC (Windows XP), bo to po prostu uruchom jako administrator, jeśli to możliwe, lub poprosi o podanie poświadczeń. Możesz sprawdzić, czy system operacyjny wymaga UAC, wykonując po prostu Environment.OSVersion.Version.Major == 6. 6 to Windows Vista i 7. Możesz upewnić się, że używasz systemu Windows, patrząc na Environment.OSVersion.Platform.

Do wykrywania czy jesteś aplikacja jest już administratorem, można to zrobić:

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

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

    return false; 
} 
+0

YOU powinien wykryć, czy użytkownik jest aktualnie uruchomiony jako administrator. Jeśli tak, możesz chcieć zachowywać się inaczej (np. Nie uruchamiać osobnej instancji i ewentualnie pomijać ikonę tarczy). – Brian

+0

@Brian, Jak zaznaczył, nie chce, aby cała aplikacja działała jako administrator, więc w tej sytuacji nie ma nic do wykrycia. Chyba że odnosisz się do faktycznego konta administratora, gdzie nawet system Windows nadal używa tarczy. –

+0

@Matthew: Tak, wiem, że OP nie chce, aby aplikacja działała jako administrator. To nie znaczy, że użytkownik nie uruchomi go jako administrator, np. ponieważ użytkownik jest w systemie Windows XP, celowo korzysta z kliknięcia prawym przyciskiem myszy jako administrator lub użytkownik wyłączył funkcję Kontrola konta użytkownika. – Brian

9

Matthew Ferreira's answer idzie do szczegółów o tym, dlaczego trzeba ponownie uruchomić całą aplikację i co zrobić, gdy się go ponownie uruchomić jednak nie zakrył, jak pokazać ikonę tarczy. Oto kod używam (myślę, że pierwotnie dostał go od innej odpowiedzi gdzieś na tej stronie), który pokaże tylko ikonę tarczy, gdy program nie jest podwyższone

/// <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); 
    } 
} 

Kontrole przycisk, gdy jest on skonstruowany jeśli znajduje się w kontekście administracyjnym, a jeśli nie, rysuje ikonę tarczy na przycisku.

Jeśli chcesz, aby okno z ikonami tarcz zawierało, here is a sneaky trick, które zwraca ikonę tarczy jako obiekt Bitmap.

Powiązane problemy