Как запросить доступ администратора к пакетному файлу

Я пытаюсь написать пакетный файл для моих пользователей для запуска с их машин Vista с UAC. Файл перезаписывает файл своих хостов, поэтому его нужно запускать с разрешениями администратора. Мне нужно иметь возможность отправить им электронное письмо со ссылкой на файл .bat. Желаемое поведение заключается в том, что, когда они щелкают правой кнопкой мыши по файлу и говорят "Открыть", они получат один из этих диалоговых окон UAC, которые заставляют экран темнеть и заставляют их отвечать, хотят ли они предоставить разрешение на использование приложения как администратора. Вместо этого они просто видят "Доступ запрещен" в окне командной строки.

Можно ли это сделать иначе?

Ответ 1

Этот скрипт делает свое дело! Просто вставьте его в верхнюю часть вашего файла летучей мыши. Если вы хотите просмотреть вывод вашего скрипта, добавьте команду "пауза" внизу вашего пакетного файла.

ОБНОВЛЕНИЕ: Этот скрипт теперь немного отредактирован для поддержки аргументов командной строки и 64-битной ОС.

Спасибо, 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"
:--------------------------------------    
    <YOUR BATCH SCRIPT HERE>

Ответ 2

Здесь используется один лайнер, который я использовал:

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

echo main code here
pause

Заметки:

  • Испытывать только на окнах 7 и 10, вам, возможно, придется возиться с цитированием
  • Пока не поддерживает передачу аргументов

Ответ 3

Вот мой код! Он выглядит большим, но в основном это строки комментариев (строки, начинающиеся с::).

Особенности:

  • Пересылка полного аргумента
  • Не меняет рабочую папку
  • Обработка ошибок
  • Принимает пути со скобками (кроме папки% TEMP%)
  • Поддерживает пути UNC
  • Проверка подключенной папки (предупреждает, что если администратор не может получить доступ к подключенному диску)

  • Может использоваться как внешняя библиотека (отметьте мой пост в этом разделе: fooobar.com/questions/10743/...)

  • Может быть вызван при необходимости/в любом месте вашего кода

Просто присоедините это к концу вашего пакетного файла или сохраните его как библиотеку (проверьте выше)

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

Пример использования

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

Ответ 4

Другой подход заключается в

  • создать ярлык локально и настроить его для вызова прав администратора [Свойства, Дополнительно, Запуск от имени администратора]

а затем

  • отправьте своим пользователям ярлык [или ссылку на ярлык, а не на сам пакетный файл].

Денис

[Добавлено потом - Да, я не заметил даты этого потока.]

Ответ 5

Решение Бен Грипки вызывает бесконечные петли. Его партия работает так (псевдокод):

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

Как вы можете видеть, это вызывает бесконечный цикл, если VBS не запрашивает права администратора.

Однако бесконечный цикл может произойти, хотя админы priviliges были запрошены успешно.

Проверка в командном файле Ben Gripka просто подвержена ошибкам. Я играл с партией и наблюдал, что привилегии администратора доступны, хотя проверка завершилась неудачно. Интересно, что проверка работала, как ожидалось, если я начал командный файл из Windows Explorer, но это не произошло, когда я начал его с моей 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

Это не вызывает бесконечных циклов, а также удаляет проверку привилегий администратора, подверженных ошибкам.

Ответ 6

Я знаю, что это не решение для OP, но, поскольку я уверен, что здесь есть много других вариантов использования, я думал, что хочу поделиться.

У меня были проблемы со всеми примерами кода в этих ответах, но я обнаружил: http://www.robotronic.de/runasspcEn.html

Он не только позволяет вам запускаться как admin, он проверяет файл, чтобы убедиться, что он не был взломан, и надежно хранит необходимую информацию. Я признаю, что это не самый очевидный инструмент для определения того, как использовать, но для тех из нас, кто пишет код, он должен быть достаточно простым.

Ответ 7

@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 будет изменен на каталог, содержащий пакетный файл)

Ответ 8

Так как у меня возникают проблемы с этим script появлением новой командной строки, которая сама запускается снова, в бесконечном цикле (используя Win 7 Pro), я предлагаю вам попробовать другой подход: Как я могу автоподнять мой пакетный файл, чтобы он запрашивал у администратора права UAC, если это необходимо?

Будьте осторожны, вы должны добавить это в конце script, как указано в правиле, чтобы вернуться в каталог script после повышения привилегий:   cd/d% ~ dp0

Ответ 9

Основываясь на сообщении от toster-cx и других интересных сообщений на этой странице, я получил представление о том, как настроить и решить мою проблему. У меня была аналогичная проблема, когда я хотел, чтобы утилита Disk Cleanup запускалась каждую неделю дважды в понедельник и четверг во время обеда (например, 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]

Его сообщение помогло настроить необязательный аргумент при планировании задачи.

Ответ 10

Еще одно решение PowerShell...

Речь идет не о запуске пакетного сценария от имени администратора, а о том, как извлечь другую программу из пакета...

У меня есть пакетный файл "обертка" для EXE. У них такое же "имя корневого файла", но альтернативные расширения. Я могу запустить exe файл от имени администратора и установить рабочий каталог на тот, который содержит скрипт, со следующим одной строкой вызова powershell:

@powershell "Start-Process -FilePath '%~n0.exe' -WorkingDirectory '%~dp0' -Verb RunAs"

Подробнее

Есть целый ряд дополнительных опций Start-Process, которые вы можете применить! Проверить: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-6

Обратите внимание, что я использую префикс @. Это эквивалентно @echo off для одной строки. Я использую %~n0 здесь, чтобы получить "корневое имя" пакетного сценария, затем объединяю .exe, чтобы указать ему вспомогательный двоичный файл. Использование %~dp0 обеспечивает полный путь к каталогу, в котором находится пакет. И, конечно же, параметр -Verb RunAs обеспечивает высоту.

Ответ 11

Вы не можете запрашивать права администратора из пакетного файла, но вы можете написать хост Windows scripting script в% temp% и запустить его (и это, в свою очередь, выполняет вашу партию как администратор). Вы хотите вызвать ShellExecute метод в объекте Shell.Application с "runas" в качестве глагола

Ответ 12

используйте команду runas. Но я не думаю, что вы можете легко отправить файл .bat.