10

Pretty straightforward one that I'm having trouble finding an answer to.

serverfault previously helped me with finding a way to automate Windows updates without using WSUS. It's working fantastically, but to run it over the network, you have to first mount a shared drive. That's pretty simple XP since you just mount the drive and run the updater.

On Vista and W7, though, this all has to be done with elevated privileges to work correctly. The UAC account can't see network drives mounted by the regular user, so in order to get everything working, I have to mount the share via net use from an escalated shell. I'd like to automate mounting this share and launching the updater via a simple .bat file.

I could probably just instruct everybody to right click "Run as Administrator" on the .bat file, but I'd like to keep things as simple as possible and have the .bat automatically prompt the user to escalate their privileges.

Since these computers don't belong to us, I can't count on anything like Powershell being installed, so that rules any solution along those lines out and pretty much have to rely on things that would be included in an RTM Vista install. I'm hoping I'm mostly missing something obvious here. :)

jslaker
  • 155
  • 2
  • 2
  • 7

9 Answers9

8

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

EDIT: If you are giving the customer a single file to run, why not create a self extracting RAR with WinRAR and set the "Require Administrator" flag in SFX options? This absolves you of your limit of only 1 file, you can have all the resources you need.

Alternatively make your SFX using your favourite SFX tool and use the elevate tools above.

ta.speot.is
  • 842
  • 5
  • 9
  • I'll keep this in mind, but, again, I'm trying to avoid installing anything extra as these machines belong to third parties. – jslaker Jan 07 '10 at 13:36
  • I believe you can use them without installing them, just package them beside your batch file. – ta.speot.is Jan 07 '10 at 13:38
  • There are several files in the download, but it looks like all you'd need for your requirement would be `elevate.cmd` and `elevate.vbs` – Dennis Williamson Jan 07 '10 at 13:48
  • If I can package this all something fairly standalone/portable, it may work. I'll take a closer look at it when I have a bit more time later today. – jslaker Jan 07 '10 at 15:31
  • Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Mark Henderson Jul 17 '13 at 05:43
4

If you are prepared to convert to PowerShell this is much easier to do. This is my "Elevate-Process.ps1" script (with su as alias in my profile):

# 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

Detection of being elevated can also be done in PSH (thus you can check for elevation, and then elevate if needed):

$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
}
Richard
  • 5,309
  • 1
  • 22
  • 20
  • I figured that Powershell can do this, but again, I can't rely on Powershell being installed, and need something as fire and forget as possible. – jslaker Jan 07 '10 at 15:30
  • @jslaker: that can certainly be a problem with Vista/2008. But PSH is included with Win7/2008R2 so that should get easier. In a corporate situation, could this be the drive to get a roll out? – Richard Jan 08 '10 at 14:26
  • Well, it's not a corporate situation. There's more in the original question that I linked, but short version is that we're a PC repair shop, and this is basically all trying to work around that the WSUS license forbids you from using WSUS to deploy updates to machines that aren't licensed to your organization. These are all customer machines that could be running anything from XP RTM on up. This is why I can't really rely on anything being installed that wouldn't be included in an RTM install of any given OS. – jslaker Jan 08 '10 at 15:31
  • If you can't rely on Powershell being installed, check out the answer I've given below. – Matt Mar 20 '13 at 15:02
3

here is an example script I came up with, I hope it helps others. It's a bat file that prompts the user for permission and then escalates itself. It pipes out some vbscript which triggers the UAC prompt and then re-runs the bat file elevated... http://jagaroth.livejournal.com/63875.html

TheThing
  • 31
  • 1
2

This is what you need: http://sites.google.com/site/eneerge/home/BatchGotAdmin

Emilio
  • 31
  • 1
  • 1
    This script has a minor bug, it doesn't forward any parameters. Just put them into the command for calling your script like this: echo UAC.ShellExecute "%~s0", "%*", "", "runas", 1 >> "%temp%\getadmin.vbs" – SvenS Dec 19 '12 at 13:30
1

FusionInventory.org is an open source solution mostly used by small repair shops. It can be like your personal remotely controlled windows updater.

rjt
  • 568
  • 5
  • 25
0

If you can't rely on Powershell being installed, you can take this solution on StackOverflow:

auto-elevate with UAC using batch file

It does not require anything to be installed and runs out of the box. If you need to preserve the command-line arguments, consider this update.

Matt
  • 101
  • 3
0

None of those solutions work for a .cmd file that needs to be aware of command-line parameters. Put this at the very beginning of the .cmd file and all your problems will be solved. (This is for future people browsing this thread [I have tested this on windows XP, 7 Vista and 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---------------------
mgorven
  • 30,036
  • 7
  • 76
  • 121
Grintor
  • 11
  • 1
0

As @emilio said, that script is OK but it does not accept any arguments. Here the modified script to be compatible with arguments:

:: 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
  • 121
  • 4
-1

Have you tried the runas command?

Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148