Как я могу автоматически повысить свой пакетный файл, чтобы он запрашивал права администратора UAC при необходимости?
Я хочу, чтобы мой пакетный файл запускался только с повышенными правами. Если не повышен, предоставьте пользователю возможность перезапустить пакет как повышенный.
Я пишу пакетный файл, чтобы установить системную переменную, скопируйте два файла в Program Files местоположение и запустите установщик драйверов. Если пользователь Windows 7 / Windows Vista (ОАК включено и даже если они являются локальным администратором) запускает его без щелчка правой кнопкой мыши и выбора "Запуск от имени администратора" , они получат "доступ запрещен" копирование два файла и запись системной переменной.
Я хотел бы использовать команду для автоматического перезапуска пакета с повышенными правами, если пользователь является администратором. В противном случае, если они не являются администраторами, я хочу сказать им, что им нужны права администратора для запуска пакетного файла. Я использую xcopy для копирования файлов и REG ADD для записи системной переменной. Я использую эти команды для работы с возможными машинами Windows XP. Я нашел аналогичные вопросы по этой теме, но ничего, что касается перезапуска пакетного файла с повышенными правами.
10 ответов
вы можете вызвать сам скрипт с помощью psexec ' s -h
возможность запуска повышенных.
Я не уверен, как вы обнаружите, если он уже работает как повышенный или нет... может быть, повторите попытку с повышенными perms, только если есть ошибка отказа в доступе?
или, вы могли бы просто иметь команды xcopy
и reg.exe
всегда работать с psexec -h
, но это было бы раздражает для конечного пользователя, если им нужно вводить свой пароль каждый раз (или небезопасно, если вы включили пароль в скрипт)...
существует простой способ без необходимости использовать внешний инструмент - он отлично работает с ОС Windows 7, 8, 8.1 и 10 и обратно совместим (Windows XP не имеет UAC, поэтому высота не требуется - в этом случае скрипт просто продолжается).
проверьте этот код (я был вдохновлен кодом NIronwolf, размещенным в потоке Пакетный Файл - "Доступ Запрещен" В Windows 7?), но я улучшил его - в моей версии есть не создается и не удаляется какой-либо каталог для проверки прав администратора):
::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
::::::::::::::::::::::::::::::::::::::::::::
@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 попросит вас три раза для вашего пользователя и пароля администратора-теперь вас спрашивают только один раз на начало, и только при необходимости.
если ваш скрипт просто должен показать сообщение об ошибке и выйти, если нет никаких прав администратора вместо auto-elevating, это еще проще: вы можете достичь этого, добавив следующее В начале вашего скрипта:
@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
.
обновление:
чтобы избежать необходимости регистрации
Как упоминали jcoder и Мэтт, PowerShell упростил его, и он даже может быть встроен в пакетный скрипт без создания нового скрипта.
Я изменил сценарий Мэтта:
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges
) else ( powershell "saps -filepath %0 -verb runas" >nul 2>&1)
exit /b
нет никакой необходимости :getPrivileges
метки.
Я использую отличный ответ Мэтта, но я вижу разницу между моими системами Windows 7 и Windows 8 при запуске повышенных скриптов.
как только скрипт повышен в Windows 8, текущий каталог установлен в C:\Windows\system32
. К счастью, есть простой обходной путь, изменив текущий каталог на путь текущего скрипта:
cd /d %~dp0
Примечание:cd /d
чтобы убедиться, что буква диска изменилась.
чтобы проверить эту, в сценарий можно скопировать следующее. Нормально работать на любой версии, чтобы увидеть тот же результат. Запуск от имени администратора и увидеть разницу в Windows 8:
@echo off
echo Current path is %cd%
echo Changing directory to the path of the current script
cd %~dp0
echo Current path is %cd%
pause
Я делаю это так:
NET SESSION
IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
GOTO ADMINTASKS
:ELEVATE
CD /d %~dp0
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
EXIT
:ADMINTASKS
(Do whatever you need to do here)
EXIT
таким образом, это просто и использовать только команды windows по умолчанию. Это здорово, если вам нужно перераспределить пакетный файл.
CD /d %~dp0
устанавливает текущий каталог в текущий каталог файла (если это еще не так, независимо от диска, на котором находится файл, благодаря ).
%~nx0
возвращает текущее имя файла с расширением (если вы не включаете расширение и есть exe с тем же именем на папка, она будет вызывать exe).
есть много ответов на этот пост я даже не знаю, если мой ответ будет видно.
в любом случае, я нахожу этот способ проще, чем другие решения, предложенные на других ответах, я надеюсь, что это кому-то поможет.
Matt имеет отличный ответ, но он удаляет любые аргументы, переданные скрипту. Вот моя модификация, которая сохраняет аргументы. Я также включил исправление Стивена для Проблемы рабочего каталога в Windows 8.
@ECHO OFF
setlocal EnableDelayedExpansion
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto START ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' ( goto START )
set "batchPath=%~f0"
set "batchArgs=ELEV"
::Add quotes to the batch path, if needed
set "script=%0"
set script=%script:"=%
IF '%0'=='!script!' ( GOTO PathQuotesDone )
set "batchPath=""%batchPath%"""
:PathQuotesDone
::Add quotes to the arguments, if needed.
:ArgLoop
IF '%1'=='' ( GOTO EndArgLoop ) else ( GOTO AddArg )
:AddArg
set "arg=%1"
set arg=%arg:"=%
IF '%1'=='!arg!' ( GOTO NoQuotes )
set "batchArgs=%batchArgs% "%1""
GOTO QuotesDone
:NoQuotes
set "batchArgs=%batchArgs% %1"
:QuotesDone
shift
GOTO ArgLoop
:EndArgLoop
::Create and run the vb script to elevate the batch file
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"
ECHO UAC.ShellExecute "cmd", "/c ""!batchPath! !batchArgs!""", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"
"%temp%\OEgetPrivileges.vbs"
exit /B
:START
::Remove the elevation tag and set the correct working directory
IF '%1'=='ELEV' ( shift /1 )
cd /d %~dp0
::Do your adminy thing here...
Я использую PowerShell для повторного запуска сценария с повышенными правами, если это не так. Поставьте эти строки в самом верху сценария.
net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~fnx0 %*'"
goto :eof
:run
:: TODO: Put code here that needs elevation
Я скопировал метод "net name" из ответа @Matt. Его ответ гораздо лучше документирован и имеет сообщения об ошибках и тому подобное. Это имеет то преимущество, что PowerShell уже установлен и доступен в Windows 7 и выше. Нет временного VBScript (*.VBS) файлы, и вам не нужно загружать инструменты.
этот метод должен работать без любая конфигурация или настройка, если разрешения на выполнение PowerShell не заблокированы.
для некоторых программ, устанавливающих супер секрет __COMPAT_LAYER
переменные среды RunAsInvoker
совместимость.Проверьте это :
set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe
хотя, как это не будет никакого запроса UAC пользователь будет продолжать без разрешений администратора.
я вставил это в начало скрипта:
:: BatchGotAdmin
:-------------------------------------
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.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"
echo args = "" >> "%temp%\getadmin.vbs"
echo For Each strArg in WScript.Arguments >> "%temp%\getadmin.vbs"
echo args = args ^& strArg ^& " " >> "%temp%\getadmin.vbs"
echo Next >> "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", args, "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs" %*
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
:--------------------------------------
следующее решение чисто и работает отлично.
скачать поднять zip-файл изhttps://www.winability.com/download/Elevate.zip
внутри zip вы должны найти два файла: Elevate.exe и Elevate64.исполняемый. (Последний является собственной 64-разрядной компиляцией, если вам это требуется, хотя обычная 32-разрядная версия повышается.exe, должен отлично работать как с 32 -, так и с 64-разрядными версиями Windows)
скопируйте файл Elevate.exe в папку, где Windows всегда может найти его (например, C:/Windows). Или вы лучше можете скопировать в ту же папку, где вы планируете сохранить файл bat.
чтобы использовать его в пакетном файле, просто добавьте команду, которую вы хотите выполнить как администратор, с помощью команды elevate, например:
elevate net start service ...