Существует простой способ без необходимости использования внешнего инструмента - он отлично работает с Windows 7, 8, 8.1 и 10 и обратно совместим (также Windows XP не имеет UAC, поэтому повышение прав не требуется - в этом на всякий случай скрипт просто продолжается).
Проверьте этот код (я был вдохновлен кодом от NIronwolf, размещенным в ветке Batch File - «Доступ запрещен» в 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, поэтому скрипт вызывает себя снова и снова.
Я исправил это сейчас, убрав кавычки в пути и добавив их позже, и добавил дополнительный параметр, который добавляется при повторном запуске сценария с повышенными правами.
Двойные кавычки удаляются следующим (подробности здесь ):
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"
.
Если вы хотите отладить сценарий VBS, вы можете добавить //X
параметр в WScript.exe в качестве первого параметра, как предлагается здесь (он описан для CScript.exe, но работает и для WScript.exe).
Полезные ссылки: