2009-07-27 10 views
12

¿Alguien sabe cómo puedo verificar programáticamente (usando C#) si mi programa podrá leer/escribir una clave de registro particular (específicamente: "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run")?¿Cómo puedo verificar si un usuario puede leer/escribir una clave de registro en particular?

Pregunto porque mi programa tiene la opción de habilitar o deshabilitar el comportamiento 'ejecutar al inicio'. Deseo desactivar esta opción si el usuario actual no puede realizar cambios en el registro. ¿El usuario actual siempre puede escribir esta clave, o existe la posibilidad de que se haya bloqueado? Si es este último, ¿cómo verifico esto?

He visto varias formas contradictorias de comprobar los permisos de registro, pero básicamente no puedo encontrar una forma de verificar una clave específica antes de intentar leerla. Prefiero realizar el control antes de acceder a la clave que intentar acceder a ella y recibir una excepción.

Cualquier ayuda es muy apreciada.

Tom

+2

Como regla general, las claves de máquina locales requieren permiso de administrador pero las claves de usuario actuales no. – Brian

+0

Gracias Brian, por lo que es seguro asumir que puedo escribir en esta clave (que se dirigirá a la tecla de usuario) y simplemente mantener la opción habilitada en todo momento, y luego solo manejar las excepciones que pueda arrojar si falla. – Beardy

Respuesta

13

La clase RegistryPermission rige los permisos de seguridad alrededor de las claves de registro. Para comprobar si es posible que tenga acceso de escritura a un permiso que lo utilice de la siguiente manera:

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

A continuación, utilizar el método de la "demanda" en un try/catch y regresar en caso de fallo (la crianza de un valor excepción). En caso de éxito, continuaría y realizaría su actualización. Aunque esto no es exactamente lo que quiere, verificar los permisos antes del acceso, es la forma aceptada de garantizar que tenga los permisos que necesita antes de operar con las claves.De una manera más o menos estructurado esto equivaldría 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: Pensando en lo que he mencionado en el comentario, aquí están los métodos de extensión a la clase RegistryPermission para comprobaciones de permisos:

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

Gracias wolfwyrd :) – Beardy

+0

No hay problema, y ​​para obtener la funcionalidad en el estilo del comentario sobre la respuesta de Joel Coehoorn, siempre puedes envolver esta prueba/atrapar un método en su clase (o como un método de extensión para el Registro) y devolver el verdadero/falso que desea ver – Wolfwyrd

+0

^^ Acabo de hacer eso ahora: P – Beardy

0

No estoy seguro de cómo es con C#, pero con Win32, usaría RegGetKeySecurity(). Tal vez hay un contenedor C#? De lo contrario, use P/Invoke.

6

Una cosa que debes saber sobre los permisos es que son volátiles. Eso significa que puede hacer su comprobación de seguridad en la clave de registro, intentar agregar su valor solo si pasa la verificación, y luego aún falla con una excepción de acceso insuficiente porque los permisos cambiaron entre cuando hizo el cheque y cuando actuó en los resultados. Esto es posible incluso si son declaraciones consecutivas en su programa.

Los permisos de seguridad concedidos tienden a ser relativamente estables, pero aún existe la posibilidad. Esto significa que debe tener código para manejar la excepción de seguridad, y si tiene que hacer eso de todos modos, en realidad no tiene sentido hacer la verificación en primer lugar. En su lugar, dedique su tiempo a hacer que su manejador de excepciones sea un poco mejor.

Dicho esto, "abucheo" a cualquier aplicación que quiera ejecutar algo en la puesta en marcha. YAGNI.

+0

Bueno, la aplicación no se configura para ejecutarse en el inicio de forma predeterminada, pero existe una buena posibilidad de que el usuario desee este comportamiento de todos modos, debido a la naturaleza/el propósito del producto. Es mejor hacerlo disponible en lugar de forzar al usuario a hacerlo manualmente. Quiero que el comportamiento get/set utilice el manejo de excepciones, pero en el cuadro de diálogo de opciones prefiero usar algo como RunAtStartup.Enabled = Registry.CanWriteToKey(), si se entiende la idea. No tiene mucho sentido para mí convertir una excepción en una booleana:/ – Beardy

5

Creo que lo mejor es intentar agregar su valor a la clave y manejar el error con elegancia informando al usuario que no tiene suficientes permisos para hacerlo.

Si está escribiendo algún tipo de herramienta administrativa diseñada para que siempre la ejecute un administrador, debe indicarla en el manifest. De esta forma, su aplicación se elevará al inicio (a través del aviso de UAC).

0

Justo intente abrir la clave de registro con los permisos de ESCRITURA.

Dicho esto, lo que otros han dicho es correcto: no hay forma de saber si una operación tendrá éxito a menos que la intente. Quizás alguien borró la tecla Ejecutar. Tal vez el registro excederá la memoria asignada. Quizás el disco falló.

1

La opción más simple es intentar y open la clave con acceso de escritura y ver si la obtiene. Recuerde close la clave después.

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