2009-07-27 8 views
12

Qualcuno sa come posso controllare a livello di codice (utilizzando C#) se il mio programma sarà in grado di leggere/scrivere una particolare chiave di registro (in particolare: "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run")?Come verificare se un utente è autorizzato a leggere/scrivere una chiave di registro particolare?

Sto chiedendo perché il mio programma ha la possibilità di abilitare o disabilitare il comportamento di 'avvio all'avvio'. Voglio disabilitare questa opzione se l'utente corrente non è autorizzato ad apportare modifiche al registro. È possibile che questa chiave venga sempre scritta dall'utente corrente o esiste la possibilità che sia stata bloccata? Se quest'ultimo, come posso controllare questo?

Ho visto diversi modi contrastanti di controllare le autorizzazioni di registro - ma fondamentalmente non riesco a trovare un modo per controllare una chiave specifica prima di provare a leggerlo. Preferirei eseguire il controllo prima di accedere alla chiave piuttosto che provare ad accedervi e ricevere un'eccezione.

Qualsiasi aiuto è molto apprezzato.

Tom

+2

Come regola generale, le chiavi della macchina locali richiedono l'autorizzazione dell'amministratore, ma le chiavi utente corrente non fanno. – Brian

+0

Grazie Brian, quindi è logico supporre che io possa scrivere su questa chiave (sarà diretta alla chiave dell'utente) e mantenere l'opzione abilitata in ogni momento, e quindi gestire solo le eccezioni che potrebbero generare se fallisce? – Beardy

risposta

13

La classe RegistryPermission governa le autorizzazioni di sicurezza relative alle chiavi di reg. Per controllare se si può avere accesso in scrittura a un permesso di utilizzarlo nel modo seguente:

RegistryPermission perm1 = new RegistryPermission(RegistryPermissionAccess.Write, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"); 

Si potrebbe quindi utilizzare il metodo "Demand" in un try/catch e restituire in caso di fallimento (l'innalzamento di un titolo eccezione). In caso di successo avresti continuato ed eseguito il tuo aggiornamento. Anche se questo non è esattamente quello che vuoi, un controllo sulle autorizzazioni prima dell'accesso, è il modo accettato per assicurarti di disporre delle autorizzazioni necessarie prima di operare sulle chiavi.In maniera del tutto strutturato ciò equivale a:

try 
{ 
    RegistryPermission perm1 = new RegistryPermission(RegistryPermissionAccess.Write, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"); 
    perm1.Demand(); 
} 
catch (System.Security.SecurityException ex) 
{ 
    return; 
} 

//Do your reg updates here 

EDIT: pensiero su quello che ho detto nel commento, qui i metodi di estensione alla classe RegistryPermission per controlli delle autorizzazioni:

using System.Security.Permissions; 
using System.Security; 

public static class RegistryExtensions 
{ 
    public static bool HavePermissionsOnKey(this RegistryPermission reg, RegistryPermissionAccess accessLevel, string key) 
    { 
     try 
     { 
      RegistryPermission r = new RegistryPermission(accessLevel, key); 
      r.Demand(); 
      return true; 
     } 
     catch (SecurityException) 
     { 
      return false; 
     } 
    } 

    public static bool CanWriteKey(this RegistryPermission reg, string key) 
    { 
     try 
     { 
      RegistryPermission r = new RegistryPermission(RegistryPermissionAccess.Write, key); 
      r.Demand(); 
      return true; 
     } 
     catch (SecurityException) 
     { 
      return false; 
     } 
    } 

    public static bool CanReadKey(this RegistryPermission reg, string key) 
    { 
     try 
     { 
      RegistryPermission r = new RegistryPermission(RegistryPermissionAccess.Read, key); 
      r.Demand(); 
      return true; 
     } 
     catch (SecurityException) 
     { 
      return false; 
     } 
    } 
} 
+0

Grazie wolfwyrd :) – Beardy

+0

Nessun problema, e per ottenere la funzionalità nello stile al commento sulla risposta di Joel Coehoorn, puoi sempre concludere questo tentativo/prendere un metodo sulla tua classe (o magari come metodo di estensione al Registro di sistema) e restituire il vero/falso che vuoi vedere – Wolfwyrd

+0

^^ Fatto questo ora: P – Beardy

0

io non sono sicuro di come con C#, ma con Win32, è necessario utilizzare RegGetKeySecurity(). Forse c'è un wrapper C#? Altrimenti, usa P/Invoke.

6

Una cosa che dovresti sapere sulle autorizzazioni è che sono volatile. Ciò significa che puoi eseguire il controllo di sicurezza sulla chiave di registro, tentare di aggiungere il tuo valore solo se il controllo passa, e quindi fallisce ancora con un'eccezione di accesso insufficiente perché le autorizzazioni cambiano tra quando hai fatto il controllo e quando hai agito sui risultati. Questo è possibile anche se sono dichiarazioni consecutive nel tuo programma.

Le autorizzazioni di sicurezza concesse tendono ad essere relativamente stabili, ma la possibilità esiste ancora. Questo significa che tu devi avere il codice per gestire l'eccezione di sicurezza, e se devi farlo comunque non c'è davvero alcun punto nel rendere il controllo in primo luogo. Piuttosto, dedica il tuo tempo a rendere un po 'meglio il tuo gestore di eccezioni.

Detto questo, "boo" a qualsiasi app che vuole eseguire qualcosa all'avvio. YAGNI.

+0

L'app non si imposta automaticamente all'avvio per impostazione predefinita, ma ci sono buone probabilità che l'utente desideri comunque questo comportamento, a causa della natura/finalità del prodotto. Meglio renderlo disponibile piuttosto che forzare l'utente a farlo manualmente. Desidero che il comportamento get/set utilizzi la gestione delle eccezioni, ma nella finestra di dialogo delle opzioni preferisco usare qualcosa come RunAtStartup.Enabled = Registry.CanWriteToKey(), se si ottiene l'idea. Non ha molto senso per me trasformare un'eccezione in un booleano:/ – Beardy

5

Penso che la cosa migliore da fare sia cercare di aggiungere il valore alla chiave e gestire l'errore con garbo informando l'utente che non avevano abbastanza permessi per farlo.

Se si sta scrivendo una sorta di strumento amministrativo progettato per essere sempre eseguito da un amministratore, è necessario indicare che nel manifest. In questo modo la tua app aumenterà all'avvio (tramite prompt UAC).

0

Proprio prova ad aprire la chiave di registro con le autorizzazioni WRITE.

Detto questo, quello che hanno detto gli altri è giusto: non c'è modo di sapere se un'operazione avrà successo a meno che non la si provi. Forse qualcuno ha cancellato il tasto Esegui. Forse il registro supererà la memoria allocata. Forse il disco è fallito.

1

L'opzione più semplice è provare la chiave open con accesso in scrittura e vedere se si ottiene. Ricordare di close la chiave in seguito.

bool fWriteAccess; 
try { 
    Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", True).Close(); 
    fWriteAccess = True; 
} catch (SecurityException) { 
    fWriteAccess = False; 
} 
Problemi correlati