¿Elevar los privilegios del proceso mediante programación?

147

Estoy tratando de instalar un servicio usando InstallUtil.exe pero invoqué Process.Start. Aquí está el código:

ProcessStartInfo startInfo = new ProcessStartInfo (m_strInstallUtil, strExePath);
System.Diagnostics.Process.Start (startInfo);

donde m_strInstallUtilestá la ruta totalmente calificada y exe a "InstallUtil.exe" y strExePathes la ruta / nombre totalmente calificado a mi servicio.

Ejecutar la sintaxis de la línea de comandos desde un símbolo del sistema elevado funciona; desde mi aplicación (usando el código anterior) no. Supongo que estoy lidiando con un problema de elevación del proceso, entonces, ¿cómo ejecutaría mi proceso en un estado elevado? ¿Necesito mirar ShellExecuteesto?

Todo esto está en Windows Vista. Estoy ejecutando el proceso en el depurador VS2008 elevado a privilegio de administrador.

También intenté configurar, startInfo.Verb = "runas";pero no pareció resolver el problema.

Scott Marlowe
fuente
Después de haber agregado, startInfo.UseShellExecute = true;además de startInfo.Verb = "runas";que funcionó bien para mí.
Matt

Respuestas:

172

Puede indicar que el nuevo proceso debe iniciarse con permisos elevados configurando la propiedad Verb de su objeto startInfo en 'runas', de la siguiente manera:

startInfo.Verb = "runas";

Esto hará que Windows se comporte como si el proceso se hubiera iniciado desde el Explorador con el comando de menú "Ejecutar como administrador".

Esto significa que aparecerá el aviso de UAC y deberá ser reconocido por el usuario: si esto no es deseable (por ejemplo, porque sucedería en medio de un proceso largo), deberá ejecutar todo el proceso de host con permisos elevados mediante Crear e incrustar un manifiesto de aplicación (UAC) para requerir el nivel de ejecución 'más alto disponible': esto hará que aparezca la solicitud de UAC tan pronto como se inicie su aplicación, y hará que todos los procesos secundarios se ejecuten con permisos elevados sin indicaciones adicionales .

Editar: veo que acaba de editar su pregunta para indicar que "runas" no funcionó para usted. Eso es realmente extraño, como debería (y lo hace para mí en varias aplicaciones de producción). Sin embargo, exigir que el proceso padre se ejecute con derechos elevados al incrustar el manifiesto definitivamente debería funcionar.

mdb
fuente
9
"runas" tampoco funcionó para mí. ¿Podría ser que solo funciona con UAC desactivado?
Dirk Vollmar el
18
@LukePuplett les agradecería. Es una excelente manera de mitigar la instalación del kit raíz sin segregar completamente las funciones del usuario.
Colton
66
@Sparksis, pero también hay otro punto de vista. Las personas que saben cómo defender su sistema operativo, saben cómo hacerlo sin UAC. Y los usuarios ficticios, que no saben qué es la defensa, hacen clic en 'SÍ' cada vez que ven la ventana UAC. Además, nada puede evitar que los escritores de virus de hackers malos usen exploits para evitarlo;) Así que estoy de acuerdo con LukePuplett =)
Jet
24
Parece que también debes configurarlo startInfo.ShellExecute=truepara que funcione ... tampoco he podido hacer que este método funcione con archivos ejecutables que están en un recurso compartido de red (tengo que copiarlos en el directorio temporal local antes de ejecutar). ..
TCC
77
@Jet Lo siento, pero esa es la mentalidad incorrecta. Cada vez que se muestra un cuadro de diálogo UAC durante la instalación, el sistema falla. Donde es valioso es cuando ve un cuadro de UAC sin ejecutar algo que requiera elevación. No importa cuán profesional usted, cualquiera de nosotros, piense que estamos en nuestras PC, no puede bloquear mágicamente cero días / descargas automáticas (por ejemplo, una reciente en el sitio oficial del Premio Nobel). Si navegaste a ese sitio y recibiste un aviso de UAC, sabrías que algo andaba mal. Con UAC apagado, nunca sabrías que te has unido a una botnet. El costo de la advertencia anticipada es tener que hacer clic en Sí ocasionalmente
Básico
46

Este código reúne todo lo anterior y reinicia la aplicación wpf actual con privilegios de administrador:

if (IsAdministrator() == false)
{
    // Restart program and run as admin
    var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
    Application.Current.Shutdown();
    return;
}

private static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}


// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)

Actualización: se prefiere la forma de manifiesto de la aplicación:

Haga clic con el botón derecho en el proyecto en Visual Studio, agregue el nuevo archivo de manifiesto de la aplicación, cambie el archivo para que tenga que configurar el Administrador como se muestra en la figura anterior.

Un problema con la forma original: si coloca el código de reinicio en app.xaml.cs OnStartup, aún puede iniciar la ventana principal brevemente aunque se haya llamado a Apagar. Mi ventana principal explotó si app.xaml.cs init no se ejecutó y en ciertas condiciones de carrera lo haría.

Curtis Yallop
fuente
Vea a continuación las mejoras.
JCCyC
requireAdministrator no funcionó en mi caso. Así que tuve que hacerlo a tu manera. ¡Esto resolvió mi problema! gracias. Pero tuve que configurar la Aplicación de instancia única en falso.
Chris
Esto funcionó para mí. También pasé el original string[] argsal proceso reaparecido.
DotNetPadawan
7
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

Esto lo hará sin UAC, no es necesario comenzar un nuevo proceso. Si el usuario en ejecución es miembro del grupo de administración como en mi caso.

hB0
fuente
3
Al usar este código, aparece un error de permiso: "Error en la solicitud de permiso de la entidad de seguridad". :(
Leonardo
Quizás "Si el usuario en ejecución es miembro de Admin" *
hB0
1
interesante: esto puede ir en cualquier método, no solo en un método de acción (incluso lo probé en el método definido en una página ASPX)
Simon_Weaver
1

Debe usar la suplantación para elevar el estado.

WindowsIdentity identity = new WindowsIdentity(accessToken);
WindowsImpersonationContext context = identity.Impersonate();

No olvides deshacer el contexto suplantado cuando hayas terminado.

Vicepresidente de Vijesh
fuente
28
No ha dicho cómo obtener AccessToken. LogonUser proporcionará el contexto de seguridad restringido de un usuario cuando UAC esté habilitado.
cwa
Si está utilizando VSTS, puede obtener un token de acceso personal desde la configuración en el portal web. (Buscar la configuración icono al lado de la imagen del usuario.) MSDocs
Su Llewellyn