Существует простой способ без использования внешнего инструмента - он отлично работает с Windows 7, 8, 8.1 и 10 и также обратно совместим (Windows XP не имеет UACтаким образом повышение прав не требуется - в этом случае сценарий просто продолжается).
Проверьте этот код (я был вдохновлен кодом NIronwolf, размещенным в теме Batch File - "AccessЗапрещено «В Windows 7? ), но я его улучшил - в моей версии нет ни одного каталога, созданного и удаленного для проверки прав администратора):
::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
:: see "https://stackoverflow.com/a/12264592/1016343" for description
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO Running Admin shell
ECHO =============================
:init
setlocal DisableDelayedExpansion
set cmdInvoke=1
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
REM Run shell as admin (example) - put here code as you like
ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
cmd /k
Сценарий использует тот факт, что NET FILE
требует права администратора и возвращает errorlevel 1
, если у вас его нет.Повышение достигается путем создания сценария, который повторно запускает пакетный файл для получения привилегий.Это приводит к тому, что Windows отображает диалоговое окно UAC и запрашивает учетную запись администратора и пароль.
Я проверил его с Windows 7, 8, 8.1, 10 и с Windows XP - он отлично работает для всех.Преимущество заключается в том, что после начальной точки вы можете разместить все, что требует привилегий системного администратора, например, если вы собираетесь переустановить и повторно запустить службу Windows для целей отладки (предполагается, что mypackage.msi является пакетом установки службы):
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
Без этого сценария повышения привилегий UAC будет трижды запрашивать у вас имя пользователя и пароль администратора - теперь вас спрашивают только один раз в начале и только при необходимости.
Если вашему сценарию просто нужно показать сообщение об ошибке и выйти, если нет никаких привилегий администратора вместо автоподнятие, это еще проще: вы можете добиться этого, добавив следующее вначало вашего скрипта:
@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
ECHO "RUN AS ADMINISTRATOR" to run this batch. Exiting... & ECHO. &
PAUSE & EXIT /D)
REM ... proceed here with admin rights ...
Таким образом, пользователь должен щелкнуть правой кнопкой мыши и выбрать «Запуск от имени администратора» .Сценарий будет продолжен после оператора REM
, если он обнаружит права администратора, в противном случае завершится с ошибкой.Если вам не требуется PAUSE
, просто удалите его. Важно: NET FILE [...] EXIT /D)
должно быть на одной строке.Он отображается здесь в несколько строк для лучшей читаемости!
На некоторых машинах Я столкнулся с проблемами, которые уже решены в новой версии выше.Одна из них была связана с другой обработкой двойных кавычек, а другая - с тем, что UAC был отключен (установлен на самый низкий уровень) на компьютере с Windows 7, поэтому скрипт снова и снова вызывает себя.
Iисправили это сейчас, удалив кавычки в пути и добавив их позже, и я добавил дополнительный параметр, который добавляется при повторном запуске сценария с повышенными правами.
Двойные кавычки удаленыследующим образом (подробности здесь ):
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
Затем вы можете получить доступ к пути, используя !batchPath!
.Он не содержит двойных кавычек, поэтому можно с уверенностью сказать "!batchPath!"
позже в скрипте.
Строка
if '%1'=='ELEV' (shift & goto gotPrivileges)
проверяет, был ли скрипт уже вызван VBScript скрипт для повышения прав, что позволяет избежать бесконечных рекурсий.Он удаляет параметр, используя shift
.
Обновление:
Чтобы избежать необходимости регистрировать расширение .vbs
в Windows 10 , я заменил строку"%temp%\OEgetPrivileges.vbs"
от"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
в сценарии выше;также добавлено cd /d %~dp0
как предложено Стивеном (отдельный ответ) и Томашем Зато (комментарий), чтобы установить каталог скрипта по умолчанию.
Теперь скрипт учитывает параметры командной строки, передаваемые ему,Спасибо jxmallet, TanisDLJ и Peter Mortensen за наблюдения и вдохновение.
Согласно подсказке Артжома Б., я проанализировал его и заменил SHIFT
на SHIFT /1
, что сохраняетимя файла для параметра %0
Добавлено del "%temp%\OEgetPrivileges_%batchName%.vbs"
в раздел :gotPrivileges
для очистки (как предложено mlt ). Добавлен %batchName%
, чтобы избежать влияния, если вы запускаете разные партии параллельно. Обратите внимание, что вам нужно использовать for
, чтобы использовать расширенные строковые функции, такие как %%~nk
, которые извлекают только имя файла.
Оптимизированная структура скрипта, улучшения (добавлена переменная vbsGetPrivileges
, которая теперь везде упоминается, что позволяет легко изменять путь или имя файла, удаляйте файл .vbs
только в том случае, если требуется повысить пакет)
В некоторых случаях для повышения необходим другой синтаксис вызова. Если скрипт не работает, проверьте следующие параметры:
set cmdInvoke=0
set winSysFolder=System32
Либо измените 1-й параметр на set cmdInvoke=1
и проверьте, устраняет ли это уже проблему. Это добавит cmd.exe
к сценарию, выполняющему повышение прав.
Или попробуйте изменить второй параметр на winSysFolder=Sysnative
, это может помочь (но в большинстве случаев не требуется) в 64-битных системах. (ADBailey сообщил об этом). «Sysnative» требуется только для запуска 64-разрядных приложений с 32-разрядного хоста сценария (например, процесс сборки Visual Studio или вызов сценария из другого 32-разрядного приложения).
Чтобы было более понятно, как интерпретируются параметры, я теперь отображаю его как P1=value1 P2=value2 ... P9=value9
. Это особенно полезно, если вам нужно заключить такие параметры, как пути, в двойные кавычки, например, "C:\Program Files"
.
Полезные ссылки: