¿Elevando UAC a través del archivo .bat?

10

Bastante sencillo para el que tengo problemas para encontrar una respuesta.

serverfault anteriormente me ayudó a encontrar una manera de automatizar las actualizaciones de Windows sin usar WSUS. Funciona fantásticamente, pero para ejecutarlo en la red, primero debe montar una unidad compartida. Eso es bastante simple XP ya que solo montas el disco y ejecutas el actualizador.

Sin embargo, en Vista y W7, todo esto debe hacerse con privilegios elevados para funcionar correctamente. La cuenta UAC no puede ver las unidades de red montadas por el usuario habitual, por lo que para que todo funcione, tengo que montar el recurso compartido net usedesde un shell escalado. Me gustaría automatizar el montaje de este recurso compartido y el lanzamiento del actualizador a través de un simple archivo .bat.

Probablemente podría indicar a todos que hagan clic con el botón derecho en "Ejecutar como administrador" en el archivo .bat, pero me gustaría mantener las cosas lo más simples posible y hacer que .bat solicite automáticamente al usuario que escale sus privilegios.

Dado que estas computadoras no nos pertenecen, no puedo contar con nada como la instalación de Powershell, por lo que descarta cualquier solución en ese sentido y prácticamente tiene que depender de las cosas que se incluirían en una instalación de RTM Vista. Espero estar perdiendo algo obvio aquí. :)

jslaker
fuente

Respuestas:

8

http://technet.microsoft.com/en-us/magazine/2007.06.utilityspotlight.aspx

EDITAR: Si le está dando al cliente un solo archivo para ejecutar, ¿por qué no crear un RAR autoextraíble con WinRAR y establecer el indicador "Requerir administrador" en las opciones de SFX? Esto lo exime de su límite de solo 1 archivo, puede tener todos los recursos que necesita.

Alternativamente, haga su SFX usando su herramienta SFX favorita y use las herramientas de elevación de arriba.

ta.speot.is
fuente
Tendré esto en mente, pero, nuevamente, estoy tratando de evitar instalar cualquier cosa adicional ya que estas máquinas pertenecen a terceros.
jslaker
Creo que puede usarlos sin instalarlos, simplemente empaquételos junto a su archivo por lotes.
ta.speot.is
Hay varios archivos en la descarga, pero parece que todo lo que necesitaría para su requerimiento sería elevate.cmdyelevate.vbs
Pausado hasta nuevo aviso.
Si puedo empaquetar todo esto de forma bastante independiente / portátil, puede funcionar. Lo miraré más de cerca cuando tenga un poco más de tiempo más tarde hoy.
jslaker
Si bien esto puede responder teóricamente la pregunta, sería preferible incluir aquí las partes esenciales de la respuesta y proporcionar el enlace para referencia.
Mark Henderson
4

Si está preparado para convertir a PowerShell, esto es mucho más fácil de hacer. Este es mi Elevate-Process.ps1script " " (con un sualias en mi perfil):

# Updated elevate function that does not need Elevate PowerToys
# From http://devhawk.net/2008/11/08/My+ElevateProcess+Script.aspx


$psi = new-object System.Diagnostics.ProcessStartInfo
$psi.Verb = "runas"

# If passed multiple commands, or one (that isn't a folder) then execute that command:
if (($args.Length -gt 1) -or (($args.length -eq 1) -and -not (test-path $args[0] -pathType Container))) {

    $file, [string]$arguments = $args;
    $psi.FileName = $file  
    $psi.Arguments = $arguments
    [System.Diagnostics.Process]::Start($psi) | out-null
    return
}

# If from console host, handle case of one argyment that is
# a folder, to start in that folder. Otherwise start in current folder.
if ($host.Name -eq 'ConsoleHost') {
    $psi.FileName = (Get-Command -name "PowerShell").Definition
    if ($args.length -eq 0) {
        $psi.Arguments = "-NoExit -Command &{set-location '" + (get-location).Path + "'}"
    } else {
        $psi.Arguments = "-NoExit -Command &{set-location '" + (resolve-path $args[0]) + "'}"
    }
    [System.Diagnostics.Process]::Start($psi) | out-null
    return
}

# Otherwise this is some other host (which cannot be assumed to take parameters).
# So simplely launch elevated.
$psi.FileName = [system.diagnostics.process]::getcurrentprocess().path
$psi.Arguments = ""
[System.Diagnostics.Process]::Start($psi) | out-null

La detección de la elevación también se puede hacer en PSH (por lo tanto, puede verificar la elevación y luego elevar si es necesario):

$wid=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$prp=new-object System.Security.Principal.WindowsPrincipal($wid)
$adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator
$IsAdmin=$prp.IsInRole($adm)
if ($IsAdmin) {
  $host.UI.RawUI.Foregroundcolor="Red"
  write-host "`n** Elevated Session **`n" -foreground $_errorColour -background $_errorBackound
}
Ricardo
fuente
Pensé que Powershell puede hacer esto, pero de nuevo, no puedo confiar en que Powershell se instale, y necesito algo tan rápido como olvidar.
jslaker
@jslaker: eso ciertamente puede ser un problema con Vista / 2008. Pero PSH se incluye con Win7 / 2008R2, por lo que debería ser más fácil. En una situación corporativa, ¿podría ser este el impulso para lanzar?
Richard
Bueno, no es una situación corporativa. Hay más en la pregunta original que vinculé, pero la versión corta es que somos un taller de reparación de PC, y esto básicamente trata de evitar que la licencia de WSUS le prohíba usar WSUS para implementar actualizaciones en máquinas que no son con licencia para su organización. Estas son todas las máquinas de los clientes que podrían ejecutar cualquier cosa, desde XP RTM en adelante. Es por eso que realmente no puedo confiar en nada que se instale que no se incluiría en una instalación RTM de cualquier sistema operativo dado.
jslaker
Si no puede confiar en la instalación de Powershell, consulte la respuesta que he dado a continuación.
Matt
3

Aquí hay un script de ejemplo que se me ocurrió, espero que ayude a otros. Es un archivo bat que solicita permiso al usuario y luego se intensifica. Canaliza algún vbscript que desencadena el indicador UAC y luego vuelve a ejecutar el archivo bat elevado ... http://jagaroth.livejournal.com/63875.html

La cosa
fuente
2

Esto es lo que necesita: http://sites.google.com/site/eneerge/home/BatchGotAdmin

Emilio
fuente
1
Este script tiene un error menor, no reenvía ningún parámetro. Simplemente póngalos en el comando para llamar a su script de esta manera: echo UAC.ShellExecute "% ~ s0", "% *", "", "runas", 1 >> "% temp% \ getadmin.vbs"
SvenS
1

FusionInventory.org es una solución de código abierto utilizada principalmente por pequeños talleres de reparación. Puede ser como su actualizador personal de Windows controlado remotamente.

rjt
fuente
0

Ninguna de esas soluciones funciona para un archivo .cmd que necesita conocer los parámetros de la línea de comandos. Ponga esto al principio del archivo .cmd y todos sus problemas se resolverán. (Esto es para futuras personas que naveguen por este hilo [he probado esto en Windows XP, 7 Vista y 8; x86 + x64]):

@echo off
NET SESSION >nul 2>&1 && goto noUAC
title.
set n=%0 %*
set n=%n:"=" ^& Chr(34) ^& "%
echo Set objShell = CreateObject("Shell.Application")>"%tmp%\cmdUAC.vbs"
echo objShell.ShellExecute "cmd.exe", "/c start " ^& Chr(34) ^& "." ^& Chr(34) ^& " /d " ^& Chr(34) ^& "%CD%" ^& Chr(34) ^& " cmd /c %n%", "", "runas", ^1>>"%tmp%\cmdUAC.vbs"
echo Not Admin, Attempting to elevate...
cscript "%tmp%\cmdUAC.vbs" //Nologo
del "%tmp%\cmdUAC.vbs"
exit /b
:noUAC

::-----Normal Batch Starts Here---------------------
Grintor
fuente
0

Como dijo @emilio, ese script está bien pero no acepta ningún argumento. Aquí el script modificado para ser compatible con los argumentos:

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>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"
    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
-1

¿Has probado el runascomando?

Pausado hasta nuevo aviso.
fuente