Как я могу автоматически повысить свой пакетный файл, чтобы он запрашивал права администратора UAC, если это необходимо?



Я хочу, чтобы мой пакетный файл работал только с повышенными правами. Если не повышен, предоставьте пользователю возможность перезапустить пакет с повышенным уровнем.



Я пишу пакетный файл для установки системной переменной, скопируйте два файла в Program Files расположение и запустите установщик драйверов. Если пользователь Windows 7 / Windows Vista (UAC включено и даже если они являются локальным администратором) запускает его без щелчка правой кнопкой мыши и выбора "Запуск от имени администратора" , они получат копирование " отказано в доступе два файла и запись системной переменной.



Я хотел бы использовать команду для автоматического перезапуска пакета с повышенными правами, если пользователь фактически является администратором. В противном случае, если они не являются администратором, я хочу сказать им, что им нужны права администратора для запуска пакетного файла. Я использую xcopy для копирования файлов и REG ADD для записи системной переменной. Я использую эти команды для работы с возможными машинами Windows XP. Я нашел аналогичные вопросы по этой теме, но ничего, что касается перезапуска пакетного файла с повышенными правами.

987   10  

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"
:--------------------------------------

следующее решение чисто и работает отлично.

  1. скачать поднять zip-файл из https://www.winability.com/download/Elevate.zip

  2. внутри zip вы должны найти два файла: Elevate.exe и Elevate64.исполняемый. (Последняя является собственной 64-разрядной компиляцией, если вам это требуется, хотя обычная 32-разрядная версия, повышается.exe, должен отлично работать как с 32-так и с 64-разрядными версиями Windows)

  3. скопируйте файл Elevate.exe в папку, где Windows всегда может найти его (например C:/Windows). Или вы лучше можете скопировать в ту же папку, где вы планируете хранить свой файл bat.

  4. чтобы использовать его в пакетном файле, просто добавьте команду, которую вы хотите выполнить как администратор, с помощью команды elevate, например:

 elevate net start service ...

Comments

    Ничего не найдено.