I am trying to write a batch file for my users to run from their Vista machines with UAC. The file is re-writing their hosts file, so it needs to be run with Administrator permissions. I need to be able to send them an email with a link to the .bat file. The desired behavior is that when they right-click on the file and say Open, they will get one of those UAC dialogs that makes the screen go dark and forces them to answer whether they want to give the application permission to run as administrator. Instead, they are just seeing "Access denied" on the command line window.

有可能采取不同的做法吗?


当前回答

另一种方法是

在本地创建快捷方式并将其设置为调用管理员权限(属性,高级,以管理员身份运行)

然后

向用户发送快捷方式(或指向快捷方式的链接,而不是指向批处理文件本身的链接)。

其他回答

基于toster-cx的帖子和本页上其他有趣的帖子,我对如何配置和解决我的问题有了深入的了解。我也遇到过类似的问题,我希望磁盘清理工具每周在周一和周四的午餐时间(比如下午2点)运行两次。然而,这需要更高的权利。

共享批处理文件,这可能会帮助其他初学者像我-

@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

非常感谢这个论坛和Rems POST在这里[https://www.petri.com/forums/forum/windows-scripting/general-scripting/32313-schtasks-exe-need-to-pass-parameters-to-script][1]

他的帖子有助于在调度任务时配置可选参数。

我使用了多个例子来修补这个工作在一起的一行。

这将打开你的批处理脚本作为一个ADMIN +最大化窗口

只需将以下代码之一添加到批处理脚本的顶部。 两种方式都可以,只是编码方式不同。

我相信第一个例子响应最快,因为/d开关禁用了我已经启用的doskey命令。

一个例子

@ECHO OFF
IF NOT "%1"=="MAX" (powershell -WindowStyle Hidden -NoProfile -Command {Start-Process CMD -ArgumentList '/D,/C' -Verb RunAs} & START /MAX CMD /D /C %0 MAX & EXIT /B)
:--------------------------------------------------------------------------------------------------------------------------------------------------------------------

:: Your original batch code here:

:--------------------------------------------------------------------------------------------------------------------------------------------------------------------

两个例子

@ECHO OFF
IF NOT "%1"=="MAX" (powershell -WindowStyle Hidden -NoProfile -Command "Start-Process CMD -ArgumentList '/C' -Verb RunAs" & START /MAX CMD /C "%0" MAX & EXIT /B)
:--------------------------------------------------------------------------------------------------------------------------------------------------------------------

:: Your original batch code here:

:--------------------------------------------------------------------------------------------------------------------------------------------------------------------

在使用原始批处理代码时,请参阅下面的建议

完整地放置原始批处理代码

只是因为最上面的第一行代码有@ECHO OFF 但这并不意味着如果你的原始脚本不应该再包含它 也有。

这确保当脚本在一个新窗口中重新启动时,现在正在管理中运行 模式,您不会丢失预期的脚本参数/属性… 例如当前工作目录、本地变量等等

您可以从以下命令开始,以避免其中一些问题

:: Make sure to use @ECHO OFF if your original code had it
@ECHO OFF
:: Avoid clashing with other active windows variables with SETLOCAL
SETLOCAL
:: Nice color to work with using 0A
COLOR 0A
:: Give your script a name
TITLE NAME IT!

:: Ensure your working directory is set where you want it to be
:: the following code sets the working directory to the script directory folder
PUSHD "%~dp0"

THE REST OF YOUR SCRIPT HERE...

:: Signal the script is finished in the title bar
ECHO.
TITLE Done! NAME IT!
PAUSE
EXIT

本·格里普卡的解决方案导致了无限循环。他的批处理是这样工作的(伪代码):

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

正如你所看到的,如果VBS请求管理员权限失败,这将导致一个无限循环。

但是,尽管已经成功请求了管理权限,但仍可能发生无限循环。

本·格里普卡批处理文件中的检查很容易出错。我对批处理进行了研究,并观察到尽管检查失败,但管理权限可用。有趣的是,如果我从windows资源管理器启动批处理文件,检查按预期工作,但当我从我的IDE启动它时,它没有。

所以我建议使用两个单独的批处理文件。第一个生成VBS,调用第二个批处理文件:

@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"

第二个文件名为“my_commands.bat”,与第一个文件位于同一目录,包含您的实际命令:

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

这不会导致无限循环,也会删除容易出错的管理特权检查。

@echo off和title可以放在下面代码之前:

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
    <code goes here>
exit

如果你不需要担心以下问题,那么很多其他答案都是多余的:

参数 工作目录(cd %~dp0将更改为包含批处理文件的目录)

这是我的代码!它看起来很大,但主要是注释行(以::)开始的行)。

特点:

全参数转发 不更改工作文件夹 错误处理 接受带圆括号的路径(%TEMP%文件夹除外) 支持UNC路径 映射文件夹检查(警告你如果管理员不能访问映射驱动器) 可以用作外部库(查看我在这个主题的帖子:https://stackoverflow.com/a/30417025/4932683) 可以调用时/如果需要在您的代码中的任何地方

只需将其附加到批处理文件的末尾,或将其保存为库(如上所示)

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

如何使用它的例子

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