2010-10-13 23 views
14

Tengo una aplicación (servicio de Windows) que está instalada en un directorio en la carpeta Archivos de programa. Junto a esta aplicación hay otra aplicación WinForms que se utiliza para configurar el servicio (entre otras cosas). Cuando hace la configuración, guarda los cambios en un archivo de configuración que vive junto con el servicio.Forma correcta de tratar con UAC en C#

Cuando se ejecuta en Vista/Win7, UAC impide que el usuario guarde en el archivo de configuración. Lo que me gustaría hacer es:

  • poner el icono de escudo junto al elemento de menú se utiliza para configurar
  • pronta para los permisos de UAC cuando se elige este artículo
  • sólo muestra el icono/aviso cuando en una OS que lo requiera
  • sólo muestran el icono/símbolo cuando se requieren permisos (por ejemplo., si la aplicación se instala en algún lugar que no requiere el permiso UAC)

realmente no quiero correr toda la aplicación como administrador, ya que también se usa para otros fines que no requieren permisos de UAC (por lo que establecer un archivo de manifiesto de aplicación no es la solución correcta). También estoy asumiendo (corríjanme si estoy equivocado) que una vez que se otorgaron los permisos de UAC, mi proceso existente no puede realizar la acción y que tendré que comenzar un nuevo proceso.

¿Cómo puedo lograr esto?

+0

Tuve que saltar un poco por los aros para codificar esto correctamente, pero gracias a Matthew obtuve algo similar a lo que describí anteriormente. – adrianbanks

+0

Bueno para escuchar. UAC a veces hace las cosas un poco dolorosas, pero tu software es realmente mejor para eso. –

Respuesta

21

Esto es bastante fácil. Coloque un icono de escudo en el botón que guarda los cambios en el archivo de configuración, en lugar del elemento de menú. Esto sigue el comportamiento de Windows de no solicitar permisos UAC hasta el último momento. De hecho, el botón iniciará su ejecutable como administrador con una línea de comando especial (que usted decida) para guardar el archivo de configuración. Use un conducto con nombre (asegúrese de darle los permisos correctos) para pasar los datos de configuración a su segunda instancia si no desea utilizar la línea de comando para el paso de datos.

para el lanzamiento de su ejecutable:

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

Esto funciona también cuando UAC no existe (Windows XP), ya que sólo tiene que ejecutar como administrador, si es posible, o solicitar las credenciales. Puede verificar si el sistema operativo requiere UAC simplemente haciendo Environment.OSVersion.Version.Major == 6. 6 es Windows Vista y 7. Puede asegurarse de que está usando Windows mirando Environment.OSVersion.Platform.

para detectar si estás aplicación ya es admin, usted puede hacer esto:

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

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

    return false; 
} 
+0

Debería detectar si el usuario se está ejecutando actualmente como administrador. Si es así, es posible que desee comportarse de forma diferente (por ejemplo, no inicie una instancia por separado y posiblemente omita el icono del escudo). – Brian

+0

@Brian, como señaló, no quiere que toda la aplicación se ejecute como administrador, por lo que en esta situación, no hay nada que detectar. A menos que se refiera a la cuenta de administrador real, donde incluso Windows todavía usa el escudo. –

+0

@Matthew: Sí, sé que OP no quiere que la aplicación se ejecute como administrador. Eso no significa que el usuario no lo ejecute como administrador de todos modos, p. porque el usuario está en Windows XP, se usa deliberadamente con el botón derecho como administrador o el usuario ha deshabilitado el UAC. – Brian

9

Matthew Ferreira's answer entra a los detalles acerca de por qué es necesario reiniciar toda la aplicación y qué hacer cuando reiniciarlo , sin embargo, él no cubrió cómo mostrar el ícono del escudo. Aquí hay un código que utilizo (creo que fue originalmente obtenido de otra respuesta en algún lugar en este sitio) que sólo se mostrará el icono del escudo cuando el programa no está elevada

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

El botón de cheques cuando se está construyendo, si está en un contexto administrativo y si no lo es, dibuja el ícono de escudo en el botón.

Si desea que el icono del escudo windows se use, here is a sneaky trick que devuelve el icono del escudo como un objeto Bitmap.

Cuestiones relacionadas