2009-02-21 13 views
77

¡Esta pregunta se aplica a Windows Vista!¿Cómo se elevan los privilegios solo cuando es necesario?

Tengo una aplicación que normalmente funciona sin privilegios administrativos. Hay una actividad que necesita privilegios administrativos pero no quiero iniciar la aplicación con mayores privilegios cuando sé que la mayoría de las veces el usuario ni siquiera está usando esa característica.

estoy pensando en cierto método por el cual puedo elevar los privilegios de la aplicación en algún evento (como pulsar un botón). Ejemplo:

Si el usuario hace clic en este botón a continuación, se le pedirá con diálogo UAC o consentimiento. ¿Cómo puedo hacer esto?

Respuesta

52

no creo que es posible elevar el proceso actualmente en ejecución. Está integrado en Windows Vista que los privilegios de administrador se otorgan a un proceso al inicio, según tengo entendido. Si observa varios programas que utilizan UAC, debería ver que en realidad lanzan un proceso por separado cada vez que se necesita realizar una acción administrativa (el Administrador de tareas es uno, Paint.NET es otro, el último es una aplicación .NET de hecho)

La solución típica a este problema es especificar argumentos de línea de comandos cuando se inicia un proceso elevado (la sugerencia de abatishchev es una forma de hacerlo), de modo que el proceso iniciado solo sabe mostrar un cuadro de diálogo determinado y luego salir esta acción ha sido completada Por lo tanto, apenas debe ser notorio para el usuario que un nuevo proceso ha sido lanzado y luego salido, y más bien parecería como si se hubiera abierto un nuevo cuadro de diálogo dentro de la misma aplicación (especialmente si usted tiene hackers para hacer la ventana principal del proceso elevado un hijo del proceso principal). Si no necesita UI para el acceso elevado, aún mejor.

Para una discusión completa de UAC en Vista, le recomiendo que vea this very through article sobre el tema (los ejemplos de código están en C++, pero sospecho que necesitará usar WinAPI y P/Invoke para hacer la mayoría de las cosas en C# de todos modos). Esperemos que ahora, al menos, ve el enfoque correcto a tomar, aunque el diseño de un programa compatible con UAC está lejos de ser trivial ...

+4

¿Hay algún cambio con Windows 7 o la respuesta "no, usa proceso nuevo" mantiene? Gracias ... –

+2

Sin cambios con Windows 7 Me temo, lo siento. (Hasta donde yo sé, y soy un usuario/desarrollador regular en Win7.) – Noldorin

+2

Así es exactamente como lo hace el administrador de tareas. Cuando hace clic en el botón para mostrar tareas para todos los usuarios, existe el administrador de tareas actual y luego invoca otro administrador de tareas con derechos de administrador. –

13

Como se dijo there:

Process.StartInfo.UseShellExecute = true; 
Process.StartInfo.Verb = "runas"; 

se ejecutará el proceso como administrador para hacer lo que necesita con el registro, pero volver a su aplicación con la normal privilegios.

+0

que implica que abarca un nuevo proceso. ¿derecho? Estaba buscando elevar los privilegios del proceso actual en sí mismo. – Hemant

+0

Intenta usar Process.GetCurrentProcess() – abatishchev

+25

No puedes elevar un proceso actualmente en ejecución. –

13

La siguiente MSDN artículo KB 981778 describe la forma de 'auto-elevar' una aplicación:

http://support.microsoft.com/kb/981778

contiene muestras descargables en Visual C++, Visual C#, Visual Basic.NET.

Este enfoque recibe alrededor de la necesidad de iniciar un proceso separado, pero en realidad es la aplicación original que se reinicia, se ejecuta como un usuario elevados. Sin embargo, esto puede ser muy útil en algunos contextos en los que no es práctico duplicar el código en un archivo ejecutable por separado.

Para eliminar la elevación, debe salir de la aplicación.

+1

Útil para un botón, pero cuando quieres lo mismo para un elemento de menú, te espera un desastre realmente intrincado. – Nyerguds

+3

@Todd Puede encontrar el código aquí: [https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3](https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3) – Matthiee

1

Sé que esta es una publicación anterior, pero esto es en respuesta a cualquier otra persona que se encuentre con la sugerencia de MarcP. La publicación msdn a la que hace referencia reinicia las aplicaciones en todos los ejemplos de código. Los ejemplos de código usan el verbo runas propuesto ya en otras sugerencias.

he descargado el código para asegurarse, pero esto es del artículo de MSDN el original:

4. Haga clic en Sí para aprobar la elevación. Luego, la aplicación original se reinicia, ejecutándose como un administrador elevado.
5. Cierre la aplicación.

+0

¿Puedes agregar el enlace de MSDN en cuestión? No puedo encontrar un usuario llamado MarcP. – Alf

0

Tal vez alguien viene muy bien este sencillo ejemplo:

using System; 
using System.Linq; 
using System.Reflection; 
using System.Diagnostics; 
using System.Security.Principal; 
using System.Windows.Forms; 

namespace WindowsFormsApp1 
{ 
    internal static class Program 
    { 
     private class Form1 : Form 
     { 
      internal Form1() 
      { 
       var button = new Button{ Dock = DockStyle.Fill }; 
       button.Click += (sender, args) => RunAsAdmin(); 
       Controls.Add(button); 

       ElevatedAction(); 
      } 
     } 

     [STAThread] 
     internal static void Main(string[] arguments) 
     { 
      if (arguments?.Contains("/run_elevated_action") == true) 
      { 
       ElevatedAction(); 
       return; 
      } 

      Application.Run(new Form1()); 
     } 

     private static void RunAsAdmin() 
     { 
      var path = Assembly.GetExecutingAssembly().Location; 
      using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action") 
      { 
       Verb = "runas" 
      })) 
      { 
       process?.WaitForExit(); 
      } 
     } 

     private static void ElevatedAction() 
     { 
      MessageBox.Show([email protected]"IsElevated: {IsElevated()}"); 
     } 

     private static bool IsElevated() 
     { 
      using (var identity = WindowsIdentity.GetCurrent()) 
      { 
       var principal = new WindowsPrincipal(identity); 

       return principal.IsInRole(WindowsBuiltInRole.Administrator); 
      } 
     } 

    } 
} 
Cuestiones relacionadas