2010-10-13 17 views
14

Ho un'applicazione (servizio Windows) che è installata in una directory nella cartella Programmi. Accanto a questa applicazione è un'altra applicazione WinForms che viene utilizzata per configurare il servizio (tra le altre cose). Quando esegue la configurazione, salva le modifiche in un file di configurazione che vive accanto al servizio.Modo corretto per gestire l'UAC in C#

Quando si esegue Vista/Win7, UAC impedisce all'utente di salvare nel file di configurazione. Quello che vorrei fare è:

  • mettere l'icona scudo accanto alla voce di menu utilizzato per configurare
  • richiesta di permessi di UAC quando questo articolo è scelto
  • mostrano solo l'icona/messaggio quando su un OS che lo richiede
  • mostrare solo l'icona/pronta quando sono richiesti i permessi (ad es. se l'applicazione è stata installata da qualche parte che non richiede il permesso UAC)

non voglio davvero per eseguire l'intera applicazionecome amministratore, in quanto viene utilizzato anche per altri scopi che non richiedono autorizzazioni UAC (quindi l'impostazione di un file manifest dell'applicazione non è la soluzione corretta). Sto anche assumendo (correggimi se sbaglio) che una volta che sono state concesse le autorizzazioni UAC, il mio processo esistente non può eseguire l'azione e che avrò bisogno di avviare un nuovo processo.

Come posso ottenere il massimo?

+0

Ho dovuto fare un po 'di salti mortali per codificarlo correttamente, ma grazie a Matthew ho qualcosa di simile a quello che ho descritto sopra. – adrianbanks

+0

Buono a sapersi. Il controllo dell'account utente talvolta rende le cose un problema, ma il tuo software è davvero migliore. –

risposta

21

Questo è abbastanza facile. Metti un'icona a forma di scudo sul pulsante che salva le modifiche al file di configurazione, invece della voce di menu. Ciò segue il comportamento di Windows di non richiedere le autorizzazioni UAC fino all'ultimo momento. In realtà il pulsante avvierà nuovamente il tuo eseguibile come amministratore con una riga di comando speciale (che decidi tu) per eseguire il salvataggio del file di configurazione. Utilizzare una pipe denominata (assicurarsi di assegnargli le autorizzazioni corrette) per passare i dati di configurazione alla seconda istanza se non si desidera utilizzare la riga di comando per il passaggio dei dati.

per lanciare l'eseguibile:

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

Questo funziona anche quando UAC non esiste (Windows XP), perché sarà sufficiente eseguire come amministratore, se possibile, o richiedere le credenziali. È possibile verificare se il SO richiede UAC semplicemente facendo Environment.OSVersion.Version.Major == 6. 6 è sia Windows Vista che 7. È possibile accertarsi di utilizzare Windows guardando a Environment.OSVersion.Platform.

Per rilevare se siete applicazione è già amministratore, si può fare questo:

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

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

    return false; 
} 
+0

Si dovrebbe rilevare se l'utente è attualmente in esecuzione come amministratore. In tal caso, potresti voler comportarti in modo diverso (ad esempio non avviare un'istanza separata ed eventualmente omettere l'icona scudo). – Brian

+0

@ Brian, Come ha sottolineato, non vuole che l'intera applicazione venga eseguita come amministratore, quindi in questa situazione non c'è nulla da rilevare. A meno che non ti stia riferendo all'account Amministratore vero e proprio, dove anche Windows utilizza ancora lo scudo. –

+0

@Matthew: Sì, so che l'OP non vuole che l'app venga eseguita come amministratore. Ciò non significa che l'utente non lo eseguirà comunque come amministratore, ad es. poiché l'utente è su Windows XP, il clic con il pulsante destro del mouse viene utilizzato deliberatamente come amministratore oppure l'utente ha disabilitato il controllo dell'account utente. – Brian

9

Matthew Ferreira's answer va per i dettagli sul perché è necessario riavviare l'intera applicazione e cosa fare quando a riavviarlo , tuttavia, non ha spiegato come mostrare l'icona dello scudo. Ecco il codice che uso (penso che originariamente preso da un'altra risposta da qualche parte su questo sito) che mostrerà solo l'icona scudo quando il programma non è elevato

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

I controlli pulsante quando è in fase di costruzione, se è in un contesto amministrativo e se non lo è disegna l'icona scudo sul pulsante.

Se si desidera utilizzare l'icona dello scudo, Windows here is a sneaky trick restituisce l'icona scudo come un oggetto Bitmap.

Problemi correlati