Як я можу автоматично підняти свій пакетний файл, щоб він вимагав від адміністратора прав UAC, якщо потрібно?


209

Я хочу, щоб мій пакетний файл працював лише підвищеним. Якщо не підвищено, надайте користувачеві можливість відновити партію як підвищену.

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

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


2
Перевірте, що я розмістив - вам не потрібен жоден зовнішній інструмент. Сценарій автоматично перевіряє права адміністратора та при необхідності автоматично піднімає себе.
Метт

1
Подумайте, будь ласка, чи відповість Метта буде відзначеною? Мені так здається.
akauppi


Зверніть увагу на нові підказки Windows 10 у розділі коментарів до пакетного сценарію, який я опублікував.
Метт

4
Від cmd : @powershell Start-Process cmd -Verb runas. Від Powershell просто кинь @powershell. Це починається cmd з підвищеними правами.
BrunoLM

Відповіді:


20

Ви можете мати виклик сценарію сам з Psexec «s -hваріантом запуску підвищений.

Я не впевнений, як ви могли б визначити, чи він вже працює як підвищений чи ні ... можливо, повторіть спробу з підвищеними колами, лише якщо є помилка в доступі, відхилена?

Або ви можете просто мати команди для xcopyі reg.exeзавжди працювати з ним psexec -h, але це буде прикро для кінцевого користувача, якщо їм потрібно буде вводити свій пароль кожен раз (або небезпечно, якщо ви включили пароль у сценарій) ...


10
Дякуємо за відповідь. На жаль, я не думаю, що я можу використовувати що-небудь за межами запасів інструментів Windows Vista / 7, оскільки це буде виходити для клієнтів поза моїм офісом. Я не думаю, що я можу легально поширювати PSExec.
PDixon724

2
Так, я думаю, ви маєте рацію з цим - навіть якщо PSExec зараз є інструментом Microsoft (оскільки вони викупили хлопців Sysinternals!) EULA забороняє розповсюдження :(
ewall

2
Я думаю, що мої варіанти досить обмежені. Якби я знав, як кодувати в VB, я міг би зробити його exe з адміністратором маніфесту, але я навіть не знав, з чого почати. Я думаю, що я просто попередитиму на початку партії, щоб запускатись як адміністратор, якщо у них працює Windows Vista / 7. Дякую усім.
PDixon724

1
Інший сторонній інструмент, який може бути вільно перерозподіленим та легким для інтеграції та вивчення - це AutoIt ; на цій сторінці показано, як скрипт вимагає підвищених привілеїв.
ewall

4
psexec -hне працює: "Не вдалося встановити послугу PSEXESVC: доступ заборонено." Вам потрібно мати права адміністратора, щоб запустити psexec.
Ніколя

319

Існує простий спосіб без необхідності використання зовнішнього інструменту - він відмінно працює з 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).

Корисні посилання:


9
Чудова відповідь, хоча мене трохи дивує, що вам потрібно зробити все, щоб зробити щось, що явно необхідно в деяких випадках.
jcoder

50
Дійсно, такої команди, як ELEVATE, явно відсутня в пакетній мові Windows.
Метт

2
Мабуть, простіше з повноваженнями, які, здається, є схваленим сценарієм ланагування для більш складних речей, але я ніколи не
переймався

1
Синтаксис у powershell зовсім інший (синтаксис дієслова-іменника), але він дозволяє легко викликати .NET-збірки. Але впоратися з цим трохи складніше (підписання сценаріїв тощо).
Метт

2
@Matt Чи можете ви перевірити, чи є якась правда за цією відхиленою редакцією у вашій відповіді?
Artjom B.

41

Як згадували jcoder і Matt, PowerShell зробив це легко, і його можна було навіть вбудувати в пакетний сценарій без створення нового сценарію.

Я змінив сценарій Метта:

:: Check privileges 
net file 1>NUL 2>NUL
if not '%errorlevel%' == '0' (
    powershell Start-Process -FilePath "%0" -ArgumentList "%cd%" -verb runas >NUL 2>&1
    exit /b
)

:: Change directory with passed argument. Processes started with
:: "runas" start with forced C:\Windows\System32 workdir
cd /d %1

:: Actual work

3
Ви праві, якщо PowerShell встановлений, ви можете використовувати його для запуску пакетного файлу з висотою (дякую за фрагмент коду!). І так, етикетка не потрібна. Дякую за підказки, це варто +1 ... :-)
Метт

2
При виклику з cmd Powershell.exe не має опції -verb runas. Він існує, якщо ви вже в PowerShell.
Аділ Гіндістан

1
Мені дуже подобається це рішення, чудово працює для мене. У Windows 8.1 мені потрібна мітка: gotPrivileges, щоб вона працювала.
ShaunO

У мене виникає проблема, якщо цей пакетний файл віддалений на шляху UNC.
Райан Біслі

Я додав каталог змін на старті, спростив потік і трохи очистив. Робочий режим не може бути змінено через WorkingDirectoryпараметр у Start-Processз причини безпеки в runasпроцесах
ceztko

28

Я використовую відмінну відповідь Метта, але я бачу різницю між моїми системами 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

1
Добрий натяк, Стівен. Таким чином, сценарій повинен закінчуватися, cd %~dp0щоб зберегти свій поточний шлях (я припускаю, що це працює і в Win7, тому та сама команда може бути використана, хоча потрібна лише для Win8 +). +1 для цього!
Метт,

2
Зверніть увагу, це було потрібно і в моїй системі під управлінням Windows 7.
meh-uk

1
або використовувати pushd %~dp0замість цього ... чому? боpopd
Ярослав Заруба

27

Я роблю це так:

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Встановлює поточний каталог у поточний каталог файлу (якщо він ще не існує, незалежно від диска, в якому знаходиться файл, завдяки /dопції).

%~nx0 Повертає поточне ім'я файлу з розширенням (Якщо ви не включите розширення, а в папці є exe з тим самим іменем, воно викликає exe).

На цю публікацію так багато відповідей, що я навіть не знаю, чи буде відповідь моя.

У будь-якому випадку, я вважаю цей спосіб простішим, ніж інші рішення, запропоновані в інших відповідях, я сподіваюся, що це комусь допоможе.


4
cd% ~ dp0 не працюватиме на мережевих накопичувачах, замість цього використовуйте pushd% ~ dp0.
Ставм

1
Мені подобається простота цієї відповіді. І нарешті привід використовувати Jscript!
Джо Кодер

1
Магія! Велике спасибі.
Даніеле Орландо

1
@Wolf Я набрав величезну відповідь лише для того, щоб зрозуміти, що я тебе зрозумів неправильно ... Я зрозумів, що ти маєш на увазі зараз. Я відредагую його, щоб включити /d. Дякую, приятелю :) (PS: Піаніст теж тут!)
Матей Роша

1
Це чудово працює, але може бути хорошою ідеєю перемістити cdкоманду до початку (це гарантує, що шлях також доступний до підвищеного сценарію - інакше підвищений скрипт просто працює з system32). Ви також повинні перенаправити команду net на нуль, щоб приховати її вихід:net session >nul 2>&1
Nulano

23

У Метта чудова відповідь, але він позбавляє будь-яких аргументів, переданих сценарію. Ось моя модифікація, яка зберігає аргументи. Я також включив виправлення Стівена для проблеми робочого каталогу в 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...

1
Це корисна відповідь. Однак у ECHO UAC.ShellExecute....черзі, "batchArgs!"не буде розширюватися змінною. Використовуйте "!batchArgs!". Мою редакцію відхилено, тому я коментую.
полетіла цибуля

1
@fliedonion добре помічений! Я не впевнений, чому вашу редакцію було відхилено, оскільки це, безумовно, помилка друку. Я змінив сам і протестував його на Win 8.1. Тепер, щоб знайти всі сценарії, де я використовую цей код ....
jxmallett

2
Сценарій зламався при використанні цитованих аргументів, як-от test.bat "a thing"або "test script.bat" arg1 arg2. Все виправлено зараз.
jxmallett

Мені вдалося зламати це (з моєї вини: запуск сценарію з картографічного мережевого диска, оскільки адміністратор і звичайний користувач не мають однакового відображення). Все-таки: чи є спосіб побачити вихід? Для мене мені довелося знайти .vbs та змінити / c на a / K, а потім побачити це вручну.
Андреас Рейфф

21

Я використовую 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

Я скопіював метод "чистого імені" з відповіді @ Метта. Його відповідь набагато краще задокументована і містить повідомлення про помилки тощо. Цей має перевагу в тому, що PowerShell вже встановлений і доступний у Windows 7 і новіших версіях. Немає тимчасових файлів VBScript (* .vbs), і вам не потрібно завантажувати інструменти.

Цей метод повинен працювати без будь-якої конфігурації чи налаштування, якщо ваші дозволи на виконання PowerShell не заблоковані.


при наданні списку відокремлених аргументів пробілів, оточених цитатами, щоб його розглядати як єдине, ця /c %~fnx0 %*'частина, здається, залишає кожну частину, крім першої. Напр. test.bat "arg1 arg2 arg3"Лише з arg1 передається вперед
Nicolas Mommaerts

Здається, що незважаючи ні на що, Start-Process видаляє всі подвійні лапки в аргументі ..
Nicolas Mommaerts

Працює для мене! Я використовую це для netsh int set int %wifiname% Enable/Disable.
Марсло

2
У мене була така ж проблема, як у Ніколя Моммаерца вище. Я не розумію, чому це працює (найкращий вид виправлення), але такі роботи, як слід (відзначте всі додаткові лапки в кінці): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
землетруси

Ще одна проблема (незручність) полягає в тому, що скрипт призупиняється (чекає введення користувачем), якщо серверна служба не працює (у мене її відключено з причин). Я заздалегідь тестую адміністративні perms, намагаючись записати в розташування файлів HOSTS , але, можливо, краще запустити команду powershell -Verb runas , а не покладатися на включені служби Windows або намагатися файли.
script'n'code

15

Для деяких програм, які налаштовують супер секретну __COMPAT_LAYERзмінну середовища, RunAsInvoker буде працювати. Перевірте це:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Незважаючи на це, не буде ніякого UAC, що спонукає користувача продовжуватись без дозволу адміністратора.


1
Посилання на сайт Microsoft більше не працювало, тому я змінив його на вміст на archive.org. Якщо хтось може знайти робоче посилання на вміст на сайті Microsoft, але всі засоби, будь ласка, оновіть його до цього.
RockPaperLizard

1
вона все ще в середній цілісності не підвищена , тому ви не можете редагувати HKLM в regedit. Це просто пропустило уак.
HackingAddict1337

5

Я вставив це на початку сценарію:

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

2
Мені подобається обробка аргументу у вашому сценарії. Але зауважте, що caclsце застаріло в Windows 7 та новіших версіях Windows.
Метт


1
Чи знаєте ви, що рядок pushd "%CD%"зберігає поточний робочий каталог та змінює поточний робочий каталог?
Вовк

3

Я написав gsudo, для вікон : що піднімає в поточній консолі (контекст не перемикання в нове вікно), з кешем мандатних (зменшена UAC спливаючих вікон), а також зводить команду PowerShell .sudo

Це дозволяє підвищувати команди, які потребують привілеїв адміністратора, або всієї партії, якщо ви хочете. Просто передбачте перед gsudo тим, що потрібно виконувати високо.

Приклад пакетного файлу, який піднімається за допомогою gsudo:

EDIT: Нова версія вкладиша, яка працює з будь-якою мовою Windows і дозволяє уникнути проблем з whoami :

net session >nul 2>nul & net session >nul 2>nul || gsudo "%~f0" && exit /b || exit /b
:: This will run as admin ::

Альтернатива (оригінальна версія):

@echo off
  rem Test if current context is already elevated:
  whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" 1> nul 2>nul && goto :isadministrator
  echo You are not admin. (yet)
  :: Use gsudo to launch this batch file elevated.
  gsudo "%~f0"
  goto end
:isadministrator
  echo You are admin.
  echo (Do admin stuff now).
:end

Встановити:

  • через шоколадний: choco install gsudo
  • або совок: scoop install gsudo
  • або схопіть його з github: https://github.com/gerardog/gsudo

Дивіться гсудо в дії: gsudo demo


Класно. Дякую. На яких версіях Windows він працює?
RockPaperLizard

Набір тестів працює на сервері 2019, а мій місцевий вікно розробників - це Windows 10 1909.
Джерардо Гриньолі

Спасибі Герардо. Якщо хтось приміряє його на інших версіях Windows, опублікуйте свої результати.
RockPaperLizard

Я щойно тестував gsudo v0.7 на Windows 8.1 і працював. Встановити .Net Framework 4.6там не банально . На щастя choco install dotnet4.6.2принесли деякі важкодоступні залежності. Потім gsudo config Prompt "$p# "виправлено ConHostпомилку із відображенням неправильного запиту (символи послідовності втечі замість червоного різкого). @RockPaperLizard
Джерардо Гриньолі

Велике спасибі Герардо. Чи можна перекомпілювати роботу з будь-якими версіями .Net Framework до 4.6, чи це залежить від певної функціональності, характерної для 4.6?
RockPaperLizard

2

Хоча це безпосередньо не стосується цього питання, оскільки він хоче деякої інформації для користувача, google привів мене сюди, коли я хотів запустити свій .bat файл, піднятий із планувальника завдань.

Найпростішим підходом було створення ярлика до файлу .bat, оскільки для ярлика можна встановити Run as administratorбезпосередньо з розширених властивостей.

Запустивши ярлик від планувальника завдань, запустить файл .bat підвищений.


0

Використання повноважень.

Якщо файл cmd довгий, я використовую перший, щоб вимагати підвищення, а потім зателефонував тому, хто виконує фактичну роботу.

Якщо сценарій - це проста команда, все може вміститися в одному cmd-файлі. Не забудьте включити шлях до файлів скриптів.

Шаблон:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c " comands or another script.cmd go here "'"

Приклад 1:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\BIN\x.ps1"'"

Приклад 2:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "c:\bin\myScript.cmd"'"

0

Спробуйте це:

@echo off
CLS
: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 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)
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

Якщо вам потрібна інформація про цей пакетний файл, запустіть фрагмент HTML / JS / CSS:

document.getElementsByTagName("data")[0].innerHTML="ElevateBatch, version 4, release<br>Required Commands:<ul><li>CLS</li><li>SETLOCAL</li><li>SET</li><li>FOR</li><li>NET</li><li>IF</li><li>ECHO</li><li>GOTO</li><li>EXIT</li><li>DEL</li></ul>It auto-elevates the system and if the user presses No, it just doesn't do anything.<br>This CANNOT be used to create an Elevated Explorer.";
data{font-family:arial;text-decoration:none}
<data></data>


-3

Наступне рішення є чистим і працює чудово.

  1. Завантажте поштовий файл Elevate з https://www.winability.com/download/Elevate.zip

  2. Всередині zip ви повинні знайти два файли: Elevate.exe та Elevate64.exe. (Остання - це нативна 64-розрядна компіляція, якщо вам цього потрібно, хоча звичайна 32-розрядна версія, Elevate.exe, повинна добре працювати як з 32-, так і з 64-бітними версіями Windows)

  3. Скопіюйте файл Elevate.exe в папку, де Windows завжди може його знайти (наприклад, C: / Windows). Або краще, ви можете скопіювати в ту саму папку, де ви плануєте зберігати файл bat.

  4. Щоб використовувати його у пакетному файлі, просто додайте команду, яку ви хочете виконати як адміністратор, командою elevate, наприклад:

 elevate net start service ...

2
Ця команда відкриває лише діалогове вікно, що запитує користувача, чи дозволено виконання цієї команди. Отже, ви не можете використовувати цю команду в пакетному файлі, що має працювати БЕЗ взаємодії користувачів.
Radon8472

Якби можна було підняти БЕЗ взаємодії з користувачем, це була б величезна дірка в безпеці, чи не так? Кожен вірус почав би використовувати цей метод, щоб підняти себе без схвалення користувача.
Андрій Білогорцефф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.