Cómo solicitar acceso de administrador dentro de un archivo por lotes

Intento escribir un archivo por lotes para que mis usuarios se ejecuten desde sus máquinas Vista con UAC. El archivo está volviendo a escribir su archivo de hosts, por lo que debe ejecutarse con permisos de administrador. Necesito poder enviarles un correo electrónico con un enlace al archivo .bat. El comportamiento deseado es que cuando hacen clic derecho en el archivo y dicen Abrir, obtengan uno de esos cuadros de diálogo de UAC que oscurecen la pantalla y los obliga a responder si desean otorgar permiso a la aplicación para ejecutarse como administrador. En su lugar, solo están viendo “Acceso denegado” en la ventana de línea de comandos.

¿Es posible hacer esto de otra manera?

¡Este script hace el truco! Solo péguelo en la parte superior de tu archivo bat. Si desea revisar el resultado de su secuencia de comandos, agregue un comando de “pausa” en la parte inferior de su archivo por lotes.

ACTUALIZACIÓN: Este script ahora está ligeramente editado para admitir argumentos de línea de comando y un sistema operativo de 64 bits.

Gracias Eneerge @ https://sites.google.com/site/eneerge/scripts/batchgotadmin

@echo off :: BatchGotAdmin :------------------------------------- REM --> Check for permissions IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" ( >nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system" ) ELSE ( >nul 2>&1 "%SYSTEMROOT%\system32\cacls.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" set params=%* echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs" "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs" exit /B :gotAdmin pushd "%CD%" CD /D "%~dp0" :--------------------------------------  

Aquí hay una línea que he estado usando:

 @echo off if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b) echo main code here pause 

Notas:

  • Solo probado en Windows 7 y 10, es posible que tenga que perder el tiempo con las citas
  • No admite pasar argumentos por ahora

Aquí está mi código! Se ve grande, pero se trata principalmente de líneas de comentarios (las líneas comienzan con: :).

caracteristicas:

  • Reenvío completo de argumentos
  • No cambia la carpeta de trabajo
  • Manejo de errores
  • Acepta rutas con paréntesis (excepto para la carpeta% TEMP%)
  • Admite rutas UNC
  • Comprobación de carpetas mapeadas (le advierto si el administrador no puede acceder a la unidad mapeada)

  • Se puede utilizar como una biblioteca externa (consulte mi publicación en este tema: https://stackoverflow.com/a/30417025/4932683 )

  • Se puede llamar cuando / si es necesario en cualquier parte de tu código

Simplemente adjunte esto al final de su archivo por lotes, o guárdelo como una biblioteca (verifique arriba)

 ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :RequestAdminElevation FilePath %* || goto:eof :: :: By: Cyberponk, v1.5 - 10/06/2016 - Changed the admin rights test method from cacls to fltmc :: v1.4 - 17/05/2016 - Added instructions for arguments with ! char :: v1.3 - 01/08/2015 - Fixed not returning to original folder after elevation successful :: v1.2 - 30/07/2015 - Added error message when running from mapped drive :: v1.1 - 01/06/2015 :: :: Func: opens an admin elevation prompt. If elevated, runs everything after the function call, with elevated rights. :: Returns: -1 if elevation was requested :: 0 if elevation was successful :: 1 if an error occured :: :: USAGE: :: If function is copied to a batch file: :: call :RequestAdminElevation "%~dpf0" %* || goto:eof :: :: If called as an external library (from a separate batch file): :: set "_DeleteOnExit=0" on Options :: (call :RequestAdminElevation "%~dpf0" %* || goto:eof) && CD /D %CD% :: :: If called from inside another CALL, you must set "_ThisFile=%~dpf0" at the beginning of the file :: call :RequestAdminElevation "%_ThisFile%" %* || goto:eof :: :: If you need to use the ! char in the arguments, the calling must be done like this, and afterwards you must use %args% to get the correct arguments: :: set "args=%* " :: call :RequestAdminElevation ..... use one of the above but replace the %* with %args:!={a)% :: set "args=%args:{a)=!%" ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1" if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information) :: UAC.ShellExecute only works with 8.3 filename, so use %~s1 set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof) :: Remove parenthesis from the temp filename set _FN=%_FN:(=% set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat" :: Test if we gave admin rights fltmc >nul 2>&1 || goto :_getElevation :: Elevation successful (if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% )) :: Set ERRORLEVEL 0, set original folder and exit endlocal & CD /D "%~dp1" & ver >nul & goto:eof :_getElevation echo/Requesting elevation... :: Try to create %_vbspath% file. If failed, exit with ERRORLEVEL 1 echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof) echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath% :: Try to create %_batpath% file. If failed, exit with ERRORLEVEL 1 echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof) echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%" :: Run %_vbspath%, that calls %_batpath%, that calls the original file %_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof) :: Vbscript has been run, exit with ERRORLEVEL -1 echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 

Ejemplo sobre cómo usarlo

 :EXAMPLE @echo off :: Run this script with elevation call :RequestAdminElevation "%~dpfs0" %* || goto:eof echo/I now have Admin rights! echo/ echo/Arguments using %%args%%: %args% echo/Arguments using %%*: %* echo/%%1= %~1 echo/%%2= %~2 echo/%%3= %~3 echo/ echo/Current Directory: %CD% echo/ echo/This file: %0 echo/ pause &goto:eof [here you paste the RequestAdminElevation function code] 

Otro enfoque es

  • crea un acceso directo localmente y configúralo para pedir permiso de administrador [Propiedades, Avanzado, Ejecutar como administrador]

y entonces

  • envíe a sus usuarios el acceso directo [o un enlace al acceso directo en lugar de uno al archivo por lotes en sí].

Denis

[Agregado después – Sí, no noté la fecha de este hilo.]

La solución de Ben Gripka causa bucles infinitos. Su lote funciona así (pseudo código):

 IF "no admin privileges?" "write a VBS that calls this batch with admin privileges" ELSE "execute actual commands that require admin privileges" 

Como puede ver, esto causa un bucle infinito, si el VBS no puede solicitar privilegios de administrador.

Sin embargo, el ciclo infinito puede ocurrir, aunque los privilegios del administrador se han solicitado con éxito.

El control en el archivo por lotes de Ben Gripka es simplemente propenso a errores. Jugué con el lote y observé que los privilegios de administrador están disponibles aunque el cheque falló. Curiosamente, el cheque funcionó como se esperaba, si comencé el archivo por lotes desde el explorador de Windows, pero no lo hice cuando lo inicié desde mi IDE.

Así que sugiero usar dos archivos por lotes separados. El primero genera el VBS que llama al segundo archivo por lotes:

 @echo off echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" set params = %*:"="" echo UAC.ShellExecute "cmd.exe", "/c ""%~dp0\my_commands.bat"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs" 

El segundo, llamado “my_commands.bat” y ubicado en el mismo directorio que el primero contiene tus comandos reales:

 pushd "%CD%" CD /D "%~dp0" REM Your commands which require admin privileges here 

Esto no causa bucles infinitos y también elimina la verificación de privilegios de administrador proclive a errores.

Sé que esta no es una solución para OP, pero como estoy seguro de que hay muchos otros casos de uso aquí, pensé que lo compartiría.

He tenido problemas con todos los ejemplos de código en estas respuestas, pero luego encontré: http://www.robotronic.de/runasspcEn.html

No solo le permite ejecutar como administrador, sino que también verifica el archivo para asegurarse de que no ha sido alterado y almacena la información necesaria de forma segura. Admitiré que no es la herramienta más obvia para descubrir cómo usar, pero para aquellos de nosotros que escribimos código, debería ser lo suficientemente simple.

@echo off y el title pueden venir antes de este código:

 net session>nul 2>&1 if %errorlevel%==0 goto main echo CreateObject("Shell.Application").ShellExecute "%~f0", "", "", "runas">"%temp%/elevate.vbs" "%temp%/elevate.vbs" del "%temp%/elevate.vbs" exit :main  exit 

Muchas de las otras respuestas son excesivas si no tiene que preocuparse por lo siguiente:

  • Parámetros
  • Directorio de trabajo ( cd %~dp0 cambiará al directorio que contiene el archivo por lotes)

Como tengo problemas con este script que muestra un nuevo símbolo del sistema y se ejecuta de nuevo, en bucle infinito (usando Win 7 Pro), le sugiero que intente con otro enfoque: ¿Cómo puedo elevar automáticamente mi archivo de proceso por lotes, para que lo solicite? Derechos de administrador de UAC si es necesario

Tenga cuidado, tiene que agregar esto al final de la secuencia de comandos, como se indica en una edición, para que esté de vuelta en el directorio de scripts después de que se hayan aumentado los privilegios: cd / d% ~ dp0

Basado en la publicación de toster-cx y otras publicaciones interesantes en esta página, obtuve una idea de cómo configurar y resolver mi problema. Tuve un problema similar en el que deseaba que la utilidad Disk Cleanup se ejecutara cada semana dos veces los lunes y jueves durante el horario de almuerzo (digamos a las 2:00 p.m.). Sin embargo, esto requirió derechos elevados.

Compartir archivos por lotes que podrían ayudar a otros principiantes como yo –

 @echo off echo Welcome to scheduling 'PC Maintenance Activity' ping localhost -n 3 >nul echo -- Step - 1 of 3 : Please give 'Admin' rights on next screen ping localhost -n 5 >nul if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit) cls echo -- Step - 2 of 3 : In next screen, select temp areas for cleaning during routine scheduled activity ping localhost -n 3 >nul C:\Windows\System32\cleanmgr.exe /sageset:112 cls echo Now scheduling maintenance activity... SchTasks /Create /SC WEEKLY /D MON,THU /TN PC_Cleanup /TR "C:\Windows\System32\cleanmgr.exe "/sagerun:112 /ST 14:00 cls echo -- Thanks for your co-operation -- echo -- Maintenance activity is scheduled for -- echo -- Every Monday and Thursday at 2 pm -- ping localhost -n 10 >nul 

Muchas gracias por este foro y Rems POST aquí [ https://www.petri.com/forums/forum/windows-scripting/general-scripting/32313-schtasks-exe-need-to-pass-parameters-to-script ] [1]

Su publicación ayudó a configurar argumentos opcionales mientras progtwigba la tarea.

No puede solicitar derechos de administrador desde un archivo de proceso por lotes, pero puede escribir un script de sistema de secuencias de comandos de Windows en% temp% y ejecutar eso (y eso a su vez ejecuta su lote como administrador). Desea llamar al método ShellExecute en el Shell. Objeto de aplicación con “runas” como el verbo

usa el comando runas. Pero, no creo que pueda enviar un archivo .bat fácilmente.