Quiero que mi archivo por lotes solo se ejecute elevado. Si no está elevado, proporcione una opción para que el usuario reinicie el lote como elevado.
Estoy escribiendo un archivo por lotes para establecer una variable del sistema, copiar dos archivos en una ubicación de Archivos de programa e iniciar un instalador de controladores. Si un usuario de Windows 7 / Windows Vista ( UAC habilitado e incluso si es un administrador local) lo ejecuta sin hacer clic derecho y seleccionando "Ejecutar como administrador", obtendrá 'Acceso denegado' copiando los dos archivos y escribiendo la variable del sistema .
Me gustaría usar un comando para reiniciar automáticamente el lote como elevado si el usuario es de hecho un administrador. De lo contrario, si no son administradores, quiero decirles que necesitan privilegios de administrador para ejecutar el archivo por lotes. Estoy usando xcopy para copiar los archivos y REG ADD para escribir la variable del sistema. Estoy usando esos comandos para tratar con posibles máquinas con Windows XP. He encontrado preguntas similares sobre este tema, pero nada que se ocupe de relanzar un archivo por lotes como elevado.
fuente
@powershell Start-Process cmd -Verb runas
. De Powershell simplemente suelta@powershell
. Esto comienza cmd con derechos elevados.Respuestas:
Puede hacer que el script se llame a sí mismo con la opción de psexec
-h
para ejecutar elevado.No estoy seguro de cómo detectaría si ya se está ejecutando como elevado o no ... ¿tal vez vuelva a intentarlo con permisos elevados solo si hay un error de acceso denegado?
O bien, podría simplemente tener los comandos para
xcopy
yreg.exe
siempre ejecutarse con ellospsexec -h
, pero sería molesto para el usuario final si necesita ingresar su contraseña cada vez (o inseguro si incluye la contraseña en el script) ...fuente
psexec -h
no funciona: "No se pudo instalar el servicio PSEXESVC: acceso denegado". Debe tener los derechos de administrador para ejecutar psexec.Hay una manera fácil sin la necesidad de usar una herramienta externa: funciona bien con Windows 7, 8, 8.1 y 10 y también es compatible con versiones anteriores (Windows XP no tiene ningún UAC, por lo que no es necesaria la elevación). en caso de que el script simplemente continúe).
Echa un vistazo a este código (me inspiró el código de NIronwolf publicado en el hilo Batch File - "Access Denied" en Windows 7? ), Pero lo he mejorado, en mi versión no hay ningún directorio creado y eliminado verificar privilegios de administrador):
El script aprovecha el hecho de que
NET FILE
requiere privilegio de administrador y regresaerrorlevel 1
si no lo tiene. La elevación se logra mediante la creación de un script que vuelve a iniciar el archivo por lotes para obtener privilegios. Esto hace que Windows presente el cuadro de diálogo UAC y le pide la cuenta de administrador y la contraseña.Lo he probado con Windows 7, 8, 8.1, 10 y con Windows XP, funciona bien para todos. La ventaja es que, después del punto de inicio, puede colocar cualquier cosa que requiera privilegios de administrador del sistema, por ejemplo, si tiene la intención de reinstalar y volver a ejecutar un servicio de Windows con fines de depuración (se supone que mypackage.msi es un paquete de instalación del servicio) :
Sin este script de elevación de privilegios, UAC le pediría tres veces su usuario y contraseña de administrador; ahora solo se le pide una vez al principio, y solo si es necesario.
Si su script solo necesita mostrar un mensaje de error y salir si no hay privilegios de administrador en lugar de elevarse automáticamente, esto es aún más simple: puede lograr esto agregando lo siguiente al comienzo de su script:
De esta forma, el usuario debe hacer clic derecho y seleccionar "Ejecutar como administrador" . El script continuará después de la
REM
declaración si detecta derechos de administrador; de lo contrario, saldrá con un error. Si no necesita elPAUSE
, simplemente quítelo. Importante:NET FILE [...] EXIT /D)
debe estar en la misma línea. ¡Se muestra aquí en varias líneas para una mejor legibilidad!En algunas máquinas, he encontrado problemas que ya están resueltos en la nueva versión anterior. Uno se debió al manejo diferente de comillas dobles, y el otro problema se debió al hecho de que UAC estaba deshabilitado (configurado en el nivel más bajo) en una máquina con Windows 7, por lo tanto, el script se llama a sí mismo una y otra vez.
He solucionado esto ahora eliminando las comillas en la ruta y volviéndolas a agregar más tarde, y he agregado un parámetro adicional que se agrega cuando el script se vuelve a iniciar con derechos elevados.
Las comillas dobles se eliminan de la siguiente manera (los detalles están aquí ):
Luego puede acceder a la ruta utilizando
!batchPath!
. No contiene comillas dobles, por lo que es seguro decirlo"!batchPath!"
más adelante en el script.La línea
comprueba si el script ya ha sido llamado por el script VBScript para elevar los derechos, evitando así recurrencias infinitas. Elimina el parámetro usando
shift
.Actualizar:
Para evitar tener que registrar la
.vbs
extensión en Windows 10 , he sustituido la línea"%temp%\OEgetPrivileges.vbs"
de
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
en el guión anterior; también agregado
cd /d %~dp0
según lo sugerido por Stephen (respuesta separada) y por Tomáš Zato (comentario) para establecer el directorio de script como predeterminado.Ahora el script respeta los parámetros de la línea de comandos que se le pasan. Gracias a jxmallet, TanisDLJ y Peter Mortensen por sus observaciones e inspiraciones.
Según la sugerencia de Artjom B., lo analicé y lo reemplacé
SHIFT
porSHIFT /1
, lo que conserva el nombre del archivo para el%0
parámetroSe agregó
del "%temp%\OEgetPrivileges_%batchName%.vbs"
a la:gotPrivileges
sección para limpiar (como se sugiere mlt ). Se agrega%batchName%
para evitar el impacto si ejecuta diferentes lotes en paralelo. Tenga en cuenta que debe usarfor
para poder aprovechar las funciones de cadena avanzadas, como por ejemplo%%~nk
, que extrae solo el nombre de archivo.Estructura de script optimizada, mejoras (variable agregada a la
vbsGetPrivileges
que ahora se hace referencia en todas partes que permite cambiar la ruta o el nombre del archivo fácilmente, solo elimine el.vbs
archivo si es necesario elevar el lote)En algunos casos, se requería una sintaxis de llamada diferente para la elevación. Si el script no funciona, verifique los siguientes parámetros:
set cmdInvoke=0
set winSysFolder=System32
Cambie el primer parámetro a
set cmdInvoke=1
y verifique si eso ya soluciona el problema. Se agregarácmd.exe
al script que realiza la elevación.O intente cambiar el segundo parámetro a
winSysFolder=Sysnative
, esto podría ayudar (pero en la mayoría de los casos no es necesario) en sistemas de 64 bits. (ADBailey ha informado esto). "Sysnative" solo es necesario para iniciar aplicaciones de 64 bits desde un host de script de 32 bits (por ejemplo, un proceso de compilación de Visual Studio o invocación de script desde otra aplicación de 32 bits).Para que quede más claro cómo se interpretan los parámetros, lo estoy mostrando ahora como
P1=value1 P2=value2 ... P9=value9
. Esto es especialmente útil si necesita encerrar parámetros como rutas en comillas dobles, por ejemplo"C:\Program Files"
.Si desea depurar el script VBS, puede agregar el
//X
parámetro a WScript.exe como primer parámetro, como se sugiere aquí (se describe para CScript.exe, pero también funciona para WScript.exe).Enlaces útiles:
Comillas (") , Bang (!) , Caret (^) , Ampersand (&) , Otros caracteres especiales
fuente
Como mencionaron jcoder y Matt, PowerShell lo hizo fácil, e incluso podría integrarse en el script por lotes sin crear un nuevo script.
Modifiqué el guión de Matt:
fuente
WorkingDirectory
parámetroStart-Process
debido a razones de seguridad en losrunas
procesosEstoy usando la excelente respuesta de Matt, pero veo una diferencia entre mis sistemas Windows 7 y Windows 8 cuando ejecuto scripts elevados.
Una vez que el script está elevado en Windows 8, el directorio actual se establece en
C:\Windows\system32
. Afortunadamente, hay una solución fácil al cambiar el directorio actual a la ruta del script actual:Nota: Use
cd /d
para asegurarse de que la letra de la unidad también se cambie.Para probar esto, puede copiar lo siguiente en un script. Ejecute normalmente en cualquier versión para ver el mismo resultado. Ejecútelo como administrador y vea la diferencia en Windows 8:
fuente
cd %~dp0
para mantener su ruta actual (supongo que esto también funciona en Win7, por lo que se puede usar el mismo comando, aunque solo es necesario para Win8 +). +1 por esto!pushd %~dp0
en su lugar ... ¿por qué? porquepopd
Lo hago de esta manera:
De esta manera es simple y usa solo los comandos predeterminados de Windows. Es genial si necesita redistribuir su archivo por lotes.
CD /d %~dp0
Establece el directorio actual en el directorio actual del archivo (si aún no lo está, independientemente de la unidad en la que se encuentre el archivo, gracias a/d
opción).%~nx0
Devuelve el nombre de archivo actual con la extensión (si no incluye la extensión y hay un archivo exe con el mismo nombre en la carpeta, llamará al archivo exe).Hay tantas respuestas en esta publicación que ni siquiera sé si se verá mi respuesta.
De todos modos, me parece más simple que las otras soluciones propuestas en las otras respuestas, espero que ayude a alguien.
fuente
/d
. Gracias amigo :) (PD: ¡Pianista aquí también!)cd
comando al inicio (esto asegura que la ruta también esté disponible para el script elevado; de lo contrario, el script elevado solo se ejecuta desde system32). También debe redirigir el comando net a nul para ocultar su salida:net session >nul 2>&1
Matt tiene una gran respuesta, pero elimina cualquier argumento pasado al guión. Aquí está mi modificación que guarda argumentos. También incorporé la solución de Stephen para el problema del directorio de trabajo en Windows 8.
fuente
ECHO UAC.ShellExecute....
línea,"batchArgs!"
no se expandirá la variable. Uso"!batchArgs!"
. Mi edición fue rechazada, así que comento.test.bat "a thing"
o"test script.bat" arg1 arg2
. Todo arreglado ahora.Uso PowerShell para relanzar el script elevado si no es así. Pon estas líneas en la parte superior de tu guión.
Copié el método 'nombre neto' de la respuesta de @ Matt. Su respuesta está mucho mejor documentada y tiene mensajes de error y similares. Este tiene la ventaja de que PowerShell ya está instalado y disponible en Windows 7 y versiones posteriores. No hay archivos temporales VBScript (* .vbs), y no tiene que descargar herramientas.
Este método debería funcionar sin ninguna configuración o configuración, siempre que sus permisos de ejecución de PowerShell no estén bloqueados.
fuente
/c %~fnx0 %*'
parte parece dejar cada parte además de la primera. Por ejemplo,test.bat "arg1 arg2 arg3"
solo de arg1 se pasa adelantenetsh int set int %wifiname% Enable/Disable
.net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
Para algunos programas, la configuración de la
__COMPAT_LAYER
variable de entorno súper secretaRunAsInvoker
funcionará. Verifique esto:Aunque así no habrá UAC que indique que el usuario continuará sin permisos de administrador.
fuente
regedit
. Simplemente se saltó el uac.Pegué esto al comienzo del guión:
fuente
cacls
está en desuso en Windows 7 y versiones más recientes de Windows.pushd "%CD%"
guarda el directorio de trabajo actual y cambia al directorio de trabajo actual?Escribí
gsudo
, unasudo
de las ventanas : que se eleva en la consola actual (sin cambio de contexto en nueva ventana), con una caché de credenciales (ventanas emergentes reducen UAC), y también eleva los comandos de PowerShell .Permite elevar comandos que requieren privilegios de administrador, o todo el lote, si lo desea. Simplemente anteponga
gsudo
antes de cualquier cosa que necesite correr elevada.Ejemplo de archivo por lotes que se eleva usando gsudo:
EDITAR: Nueva versión de línea única que funciona con cualquier idioma de Windows y evita problemas de whoami :
Alternativa (versión original):
Instalar en pc:
choco install gsudo
scoop install gsudo
Ver gsudo en acción:
fuente
.Net Framework 4.6
allí. Afortunadamentechoco install dotnet4.6.2
trajo algunas dependencias difíciles de obtener. Luego segsudo config Prompt "$p# "
solucionó un problema queConHost
mostraba un mensaje incorrecto (caracteres de secuencia de escape en lugar del marcado rojo). @RockPaperLizardAunque no es directamente aplicable a esta pregunta, debido a que quiere información para el usuario, Google me trajo aquí cuando quería ejecutar mi archivo .bat elevado desde el programador de tareas.
El enfoque más simple fue crear un acceso directo al archivo .bat, porque para un acceso directo puede establecer
Run as administrator
directamente desde las propiedades avanzadas.Al ejecutar el acceso directo desde el programador de tareas, se ejecuta el archivo .bat elevado.
fuente
Si no necesita pasar argumentos, aquí hay un script de solicitud de UAC compacto que tiene una sola línea de largo. Esto hace algo similar al guión de elevación en la respuesta más votada, pero no pasa argumentos, ya que no hay una manera infalible de hacer eso que maneje todas las combinaciones posibles de caracteres venenosos.
fuente
Usando PowerShell.
Si el archivo cmd es largo, utilizo el primero para requerir elevación y luego llamo al que hace el trabajo real.
Si el script es un comando simple, todo puede caber en un archivo cmd. No olvide incluir la ruta en los archivos de script.
Modelo:
Ejemplo 1:
Ejemplo 2
fuente
Prueba esto:
Si necesita información sobre ese archivo por lotes, ejecute el fragmento HTML / JS / CSS:
fuente
La siguiente solución es limpia y funciona perfectamente.
Descargue el archivo zip de Elevate desde https://www.winability.com/download/Elevate.zip
Dentro de zip debes encontrar dos archivos: Elevate.exe y Elevate64.exe. (Esta última es una compilación nativa de 64 bits, si lo requiere, aunque la versión normal de 32 bits, Elevate.exe, debería funcionar bien con las versiones de Windows de 32 y 64 bits)
Copie el archivo Elevate.exe en una carpeta donde Windows siempre pueda encontrarlo (como C: / Windows). O mejor, puede copiar en la misma carpeta donde planea mantener su archivo bat.
Para usarlo en un archivo por lotes, simplemente anteponga el comando que desea ejecutar como administrador con el comando elevar, de esta manera:
fuente