¿Cómo puedo elevar automáticamente mi archivo por lotes, para que solicite los derechos de administrador de UAC si es necesario?

209

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.

PDixon724
fuente
2
Vea lo que he publicado: no necesita ninguna herramienta externa, el script verifica automáticamente los derechos de administrador y se eleva automáticamente si es necesario.
Matt
1
¿Considera si la respuesta de Matt sería la marcada? A mí me parece así.
akauppi
Tenga en cuenta las nuevas sugerencias de Windows 10 en la sección de comentarios del script por lotes que he publicado.
Matt
44
De CMD @powershell Start-Process cmd -Verb runas. De Powershell simplemente suelta @powershell. Esto comienza cmd con derechos elevados.
BrunoLM

Respuestas:

20

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 xcopyy reg.exesiempre ejecutarse con ellos psexec -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) ...

ewall
fuente
10
Gracias por la respuesta. Desafortunadamente, no creo que pueda usar nada fuera de las herramientas de Windows Vista / 7, ya que esto se enviará a clientes fuera de mi oficina. No creo que pueda distribuir legalmente PSExec.
PDixon724
2
Sí, creo que tienes razón en eso, a pesar de que PSExec ahora es una herramienta de Microsoft (¡ya que compraron los chicos de Sysinternals!), El EULA prohíbe la distribución :(
ewall
2
Creo que mis opciones son bastante limitadas. Si supiera cómo codificar en VB, podría convertirlo en un exe con un manifiesto de administrador, pero ni siquiera sabría por dónde empezar. Supongo que solo advertiré al comienzo del lote que se ejecute como administrador si están ejecutando Windows Vista / 7. Gracias a todos.
PDixon724
1
Otra herramienta de terceros que puede redistribuirse libremente y ser fácil de integrar y aprender es AutoIt ; Esta página muestra cómo el script solicita privilegios elevados.
ewall
44
psexec -hno funciona: "No se pudo instalar el servicio PSEXESVC: acceso denegado". Debe tener los derechos de administrador para ejecutar psexec.
Nicolas
319

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):

::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
:: see "https://stackoverflow.com/a/12264592/1016343" for description
::::::::::::::::::::::::::::::::::::::::::::
 @echo off
 CLS
 ECHO.
 ECHO =============================
 ECHO Running Admin shell
 ECHO =============================

:init
 setlocal DisableDelayedExpansion
 set cmdInvoke=1
 set winSysFolder=System32
 set "batchPath=%~0"
 for %%k in (%0) do set batchName=%%~nk
 set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
 setlocal EnableDelayedExpansion

:checkPrivileges
  NET FILE 1>NUL 2>NUL
  if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )

:getPrivileges
  if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
  ECHO.
  ECHO **************************************
  ECHO Invoking UAC for Privilege Escalation
  ECHO **************************************

  ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
  ECHO args = "ELEV " >> "%vbsGetPrivileges%"
  ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
  ECHO args = args ^& strArg ^& " "  >> "%vbsGetPrivileges%"
  ECHO Next >> "%vbsGetPrivileges%"

  if '%cmdInvoke%'=='1' goto InvokeCmd 

  ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
  goto ExecElevation

:InvokeCmd
  ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
  ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"

:ExecElevation
 "%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
 exit /B

:gotPrivileges
 setlocal & cd /d %~dp0
 if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul  &  shift /1)

 ::::::::::::::::::::::::::::
 ::START
 ::::::::::::::::::::::::::::
 REM Run shell as admin (example) - put here code as you like
 ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
 cmd /k

El script aprovecha el hecho de que NET FILErequiere privilegio de administrador y regresa errorlevel 1si 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) :

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

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:

@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
  ECHO "RUN AS ADMINISTRATOR"  to run this batch. Exiting... & ECHO. &
  PAUSE & EXIT /D)
REM ... proceed here with admin rights ...

De esta forma, el usuario debe hacer clic derecho y seleccionar "Ejecutar como administrador" . El script continuará después de la REMdeclaración si detecta derechos de administrador; de lo contrario, saldrá con un error. Si no necesita el PAUSE, 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í ):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

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

if '%1'=='ELEV' (shift & goto gotPrivileges)

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 .vbsextensió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 %~dp0segú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é SHIFTpor SHIFT /1, lo que conserva el nombre del archivo para el %0parámetro

  • Se agregó del "%temp%\OEgetPrivileges_%batchName%.vbs"a la :gotPrivilegessecció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 usar forpara 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 vbsGetPrivilegesque ahora se hace referencia en todas partes que permite cambiar la ruta o el nombre del archivo fácilmente, solo elimine el .vbsarchivo 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=1y verifique si eso ya soluciona el problema. Se agregará cmd.exeal 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 //Xpará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:

Mate
fuente
9
Gran respuesta, aunque me sorprende un poco que tengas que hacer todo eso para hacer algo que es claramente necesario en algunos casos.
jcoder
50
De hecho, un comando como ELEVATE falta claramente en el lenguaje por lotes de Windows.
Matt el
2
Tal vez sea más fácil con powershell, que parece ser el lenguaje de secuencias de comandos aprobado para cosas más complejas, pero nunca me molesté en aprenderlo hasta ahora :(
jcoder
1
La sintaxis en powershell es completamente diferente (sintaxis verbo-sustantivo), pero le permite llamar a ensamblados .NET fácilmente. Pero es un poco más difícil de manejar (firmar scripts, etc.).
Matt
2
@Matt ¿Puede verificar si hay alguna verdad detrás de esta edición rechazada en su respuesta?
Artjom B.
41

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:

:: Check privileges 
net file 1>NUL 2>NUL
if not '%errorlevel%' == '0' (
    powershell Start-Process -FilePath "%0" -ArgumentList "%cd%" -verb runas >NUL 2>&1
    exit /b
)

:: Change directory with passed argument. Processes started with
:: "runas" start with forced C:\Windows\System32 workdir
cd /d %1

:: Actual work
Ir relevante
fuente
3
Tiene razón, si PowerShell está instalado, puede usarlo para ejecutar el archivo por lotes con elevación (¡gracias por el fragmento de código!). Y sí, la etiqueta no es necesaria. Gracias por las sugerencias, vale la pena un +1 ... :-)
Matt
2
Cuando se invoca desde cmd, Powershell.exe no tiene la opción -verb runas. Existe si ya está en PowerShell.
Adil Hindistan
1
Realmente me gusta esta solución, funciona muy bien para mí. En Windows 8.1 requería la etiqueta: gotPrivileges para que funcione.
ShaunO
Me encuentro con un problema si este archivo por lotes es remoto en una ruta UNC.
Ryan Beesley
Agregué el directorio de cambio al inicio, simplifiqué el flujo y limpié un poco. El directorio de trabajo no se puede cambiar a través del WorkingDirectoryparámetro Start-Processdebido a razones de seguridad en los runasprocesos
ceztko
28

Estoy 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:

cd /d %~dp0

Nota: Use cd /dpara 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:

@echo off
echo Current path is %cd%
echo Changing directory to the path of the current script
cd %~dp0
echo Current path is %cd%
pause
Stephen Klancher
fuente
1
Buena pista, Stephen. Por lo tanto, el script debe terminar cd %~dp0para 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!
Matt
2
Cabe destacar que esto también fue necesario en mi sistema con Windows 7.
meh-uk
1
o usar pushd %~dp0en su lugar ... ¿por qué? porquepopd
Jaroslav Záruba
27

Lo hago de esta manera:

NET SESSION
IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
GOTO ADMINTASKS

:ELEVATE
CD /d %~dp0
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
EXIT

:ADMINTASKS
(Do whatever you need to do here)
EXIT

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.

Matheus Rocha
fuente
44
cd% ~ dp0 no funcionará en unidades de red, use pushd% ~ dp0 en su lugar.
Stavm
1
Me encanta la simplicidad de esta respuesta. Y finalmente una razón para usar Jscript!
Joe Coder
1
¡Magia! Muchas gracias.
Daniele Orlando
1
@Wolf Escribí una gran respuesta solo para darme cuenta de que te entendí mal ... Comprendí lo que quieres decir ahora. Lo editaré para incluir el /d. Gracias amigo :) (PD: ¡Pianista aquí también!)
Matheus Rocha
1
Esto funciona muy bien, pero podría ser una buena idea mover el cdcomando 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
Nulano
23

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.

@ECHO OFF
setlocal EnableDelayedExpansion

NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto START ) else ( goto getPrivileges ) 

:getPrivileges
if '%1'=='ELEV' ( goto START )

set "batchPath=%~f0"
set "batchArgs=ELEV"

::Add quotes to the batch path, if needed
set "script=%0"
set script=%script:"=%
IF '%0'=='!script!' ( GOTO PathQuotesDone )
    set "batchPath=""%batchPath%"""
:PathQuotesDone

::Add quotes to the arguments, if needed.
:ArgLoop
IF '%1'=='' ( GOTO EndArgLoop ) else ( GOTO AddArg )
    :AddArg
    set "arg=%1"
    set arg=%arg:"=%
    IF '%1'=='!arg!' ( GOTO NoQuotes )
        set "batchArgs=%batchArgs% "%1""
        GOTO QuotesDone
        :NoQuotes
        set "batchArgs=%batchArgs% %1"
    :QuotesDone
    shift
    GOTO ArgLoop
:EndArgLoop

::Create and run the vb script to elevate the batch file
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"
ECHO UAC.ShellExecute "cmd", "/c ""!batchPath! !batchArgs!""", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"
"%temp%\OEgetPrivileges.vbs" 
exit /B

:START
::Remove the elevation tag and set the correct working directory
IF '%1'=='ELEV' ( shift /1 )
cd /d %~dp0

::Do your adminy thing here...
jxmallett
fuente
1
Esta es una respuesta útil. Sin embargo, en ECHO UAC.ShellExecute....línea, "batchArgs!"no se expandirá la variable. Uso "!batchArgs!". Mi edición fue rechazada, así que comento.
cebolla
1
@fliedonion bien visto! No estoy seguro de por qué su edición fue rechazada porque definitivamente fue un error tipográfico y su corrección funciona. Hice el cambio yo mismo y lo probé en Win 8.1. Ahora para encontrar todas las secuencias de comandos donde uso este código ....
jxmallett
2
El script se rompió al usar argumentos citados, como test.bat "a thing"o "test script.bat" arg1 arg2. Todo arreglado ahora.
jxmallett
Logré romperlo (debido a mi error: ejecutar el script desde la unidad de red asignada, ya que el administrador y el usuario normal no tienen la misma asignación). Aún así: ¿hay alguna manera de ver la salida? Para mí, tuve que encontrar .vbs y cambiar el / c a / K y luego verlo manualmente.
Andreas Reiff
21

Uso PowerShell para relanzar el script elevado si no es así. Pon estas líneas en la parte superior de tu guión.

net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~fnx0 %*'"
goto :eof
:run
:: TODO: Put code here that needs elevation

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.

Ryan Bemrose
fuente
al proporcionar una lista de argumentos separados por espacios en blanco rodeados de comillas para que se trate como uno, la /c %~fnx0 %*'parte parece dejar cada parte además de la primera. Por ejemplo, test.bat "arg1 arg2 arg3"solo de arg1 se pasa adelante
Nicolas Mommaerts
Parece que no importa qué, el proceso de inicio elimina todas las comillas dobles en la lista de argumentos ..
Nicolas Mommaerts
¡Funciona para mi! Lo estoy usando para netsh int set int %wifiname% Enable/Disable.
Marslo
2
Tuve el mismo problema que Nicolas Mommaerts arriba. No entiendo por qué funciona (el mejor tipo de solución), pero lo siguiente funciona como debería (tenga en cuenta todas las comillas adicionales al final): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
temblores
Otro problema (inconveniente) es que el script hace una pausa (espera la entrada del usuario) si el servicio del servidor no se está ejecutando (lo he deshabilitado por razones). Por lo general, pruebo los permisos de administrador al intentar escribir en la ubicación del archivo HOSTS , pero tal vez sea mejor invocar el comando powershell -Verb runas , en lugar de confiar en los servicios de Windows habilitados o intentar escribir archivos.
script'n'code
15

Para algunos programas, la configuración de la __COMPAT_LAYERvariable de entorno súper secreta RunAsInvoker funcionará. Verifique esto:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Aunque así no habrá UAC que indique que el usuario continuará sin permisos de administrador.

npocmaka
fuente
1
El enlace al sitio de Microsoft ya no funcionaba, así que lo cambié al contenido de archive.org. Si alguien puede encontrar un enlace funcional al contenido en el sitio de Microsoft, pero todos los medios, actualícelo.
RockPaperLizard
1
todavía está en integridad media no elevada , por lo que no puede editar HKLM en regedit. Simplemente se saltó el uac.
HackingAddict1337
5

Pegué esto al comienzo del guión:

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo args = "" >> "%temp%\getadmin.vbs"
    echo For Each strArg in WScript.Arguments >> "%temp%\getadmin.vbs"
    echo args = args ^& strArg ^& " "  >> "%temp%\getadmin.vbs"
    echo Next >> "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", args, "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs" %*
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------
TanisDLJ
fuente
2
Me gusta el procesamiento arg en tu script. Pero tenga en cuenta que caclsestá en desuso en Windows 7 y versiones más recientes de Windows.
Matt
Fsutil sucio es aún mejor
Wolf
1
¿Sabe que la línea pushd "%CD%"guarda el directorio de trabajo actual y cambia al directorio de trabajo actual?
Wolf
3

Escribí gsudo, una sudode 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 :

net session >nul 2>nul & net session >nul 2>nul || gsudo "%~f0" && exit /b || exit /b
:: This will run as admin ::

Alternativa (versión original):

@echo off
  rem Test if current context is already elevated:
  whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" 1> nul 2>nul && goto :isadministrator
  echo You are not admin. (yet)
  :: Use gsudo to launch this batch file elevated.
  gsudo "%~f0"
  goto end
:isadministrator
  echo You are admin.
  echo (Do admin stuff now).
:end

Instalar en pc:

Ver gsudo en acción: gsudo demo

Gerardo Grignoli
fuente
Frio. Gracias. ¿En qué versiones de Windows funciona?
RockPaperLizard
El conjunto de pruebas se ejecuta en Server 2019 y mi caja de desarrollo local es Windows 10 1909. Lo siento, no he probado la compatibilidad con otros sistemas operativos más antiguos.
Gerardo Grignoli
Gracias gerardo Si alguien lo prueba en otras versiones de Windows, publique sus resultados.
RockPaperLizard
Acabo de probar gsudo v0.7 en Windows 8.1 y funcionó. No es trivial instalarlo .Net Framework 4.6allí. Afortunadamente choco install dotnet4.6.2trajo algunas dependencias difíciles de obtener. Luego se gsudo config Prompt "$p# "solucionó un problema que ConHostmostraba un mensaje incorrecto (caracteres de secuencia de escape en lugar del marcado rojo). @RockPaperLizard
Gerardo Grignoli
Muchas gracias Gerardo. ¿Podría recompilarse para funcionar con cualquier versión de .Net Framework anterior a 4.6, o depende de alguna funcionalidad específica de 4.6?
RockPaperLizard
2

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

Hugo Delsing
fuente
1

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.

@echo off
net sess>nul 2>&1||(echo(CreateObject("Shell.Application"^).ShellExecute"%~0",,,"RunAs",1:CreateObject("Scripting.FileSystemObject"^).DeleteFile(wsh.ScriptFullName^)>"%temp%\%~nx0.vbs"&start wscript.exe "%temp%\%~nx0.vbs"&exit)

:: Your batch file goes here
usuario8922283
fuente
0

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:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c " comands or another script.cmd go here "'"

Ejemplo 1:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\BIN\x.ps1"'"

Ejemplo 2

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "c:\bin\myScript.cmd"'"
Manuel Alves
fuente
0

Prueba esto:

@echo off
CLS
:init
setlocal DisableDelayedExpansion
set cmdInvoke=1
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " "  >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd 
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul  &  shift /1)
REM Run shell as admin (example) - put here code as you like
ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
cmd /k

Si necesita información sobre ese archivo por lotes, ejecute el fragmento HTML / JS / CSS:

document.getElementsByTagName("data")[0].innerHTML="ElevateBatch, version 4, release<br>Required Commands:<ul><li>CLS</li><li>SETLOCAL</li><li>SET</li><li>FOR</li><li>NET</li><li>IF</li><li>ECHO</li><li>GOTO</li><li>EXIT</li><li>DEL</li></ul>It auto-elevates the system and if the user presses No, it just doesn't do anything.<br>This CANNOT be used to create an Elevated Explorer.";
data{font-family:arial;text-decoration:none}
<data></data>


fuente
-3

La siguiente solución es limpia y funciona perfectamente.

  1. Descargue el archivo zip de Elevate desde https://www.winability.com/download/Elevate.zip

  2. 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)

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

  4. Para usarlo en un archivo por lotes, simplemente anteponga el comando que desea ejecutar como administrador con el comando elevar, de esta manera:

 elevate net start service ...
Vaibhav Jain
fuente
2
Ese comando solo abre una ventana de diálogo que le pregunta al usuario si este comando puede ejecutarse. Por lo tanto, no puede usar este comando en un archivo por lotes que debería ejecutarse SIN interacciones del usuario.
Radon8472
Si fuera posible elevar SIN la interacción del usuario, sería un gran agujero de seguridad, ¿no? Cada virus comenzaría a usar ese método para elevarse sin la aprobación del usuario.
Andrei Belogortseff