Как я могу автоматически повысить свой пакетный файл, чтобы он запрашивал права администратора UAC, если это необходимо?
Я хочу, чтобы мой пакетный файл работал только с повышенными правами. Если не повышен, предоставьте пользователю возможность перезапустить пакет с повышенным уровнем.
Я пишу пакетный файл для установки системной переменной, скопируйте два файла в Program Files расположение и запустите установщик драйверов. Если пользователь Windows 7 / Windows Vista (UAC включено и даже если они являются локальным администратором) запускает его без щелчка правой кнопкой мыши и выбора "Запуск от имени администратора" , они получат копирование " отказано в доступе два файла и запись системной переменной.
Я хотел бы использовать команду для автоматического перезапуска пакета с повышенными правами, если пользователь фактически является администратором. В противном случае, если они не являются администратором, я хочу сказать им, что им нужны права администратора для запуска пакетного файла. Я использую xcopy для копирования файлов и REG ADD для записи системной переменной. Я использую эти команды для работы с возможными машинами Windows XP. Я нашел аналогичные вопросы по этой теме, но ничего, что касается перезапуска пакетного файла с повышенными правами.
10 ответов:
вы можете вызвать сам скрипт с помощью psexec ' s
-hвозможность запуска с повышенными правами.Я не уверен, как вы обнаружите, если он уже работает как повышенный или нет... может быть, повторите попытку с повышенными завивками, только если есть ошибка отказа в доступе?
или, вы могли бы просто иметь команды
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 запросит у вас три раза для вашего администратора пользователя и пароль-Теперь вас спрашивают только один раз начало, и только при необходимости.
если ваш скрипт просто должен показать сообщение об ошибке и выйти, если нет никаких прав администратора вместо автоматическое повышение, это еще проще: вы можете достичь этого, добавив следующее В начале вашего скрипта:
@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 и Matt, 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).есть много ответов на этот пост я даже не знаю, если мой ответ будет видно.
в любом случае, я нахожу этот способ проще, чем другие решения, предложенные на других ответах, я надеюсь, что это поможет кому-то.
у Мэтта есть отличный ответ, но он удаляет любые аргументы, переданные сценарию. Вот моя модификация, которая сохраняет аргументы. Я также включил исправление Стивена для Проблемы рабочего каталога в 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 ...
Comments