Існує простий спосіб без необхідності використання зовнішнього інструменту - він відмінно працює з Windows 7, 8, 8.1 та 10, а також сумісний із зворотним ходом (Windows XP не має жодного UAC, тому висота не потрібна - в тому, що випадку сценарій просто продовжується).
Перевірте цей код (мене надихнув код NIronwolf, розміщений у потоці Пакетний файл - " Заборонено доступ" у 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 за спостереження та натхнення.
Згідно з підказкою Artjom B., я проаналізував його та замінив 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).
Корисні посилання: