Làm cách nào để yêu cầu quyền truy cập của Quản trị viên trong một tệp bó


179

Tôi đang cố gắng viết một tệp bó để người dùng của tôi chạy từ máy Vista của họ bằng UAC. Tệp đang ghi lại tệp máy chủ của họ, vì vậy nó cần được chạy với quyền của Quản trị viên. Tôi cần có thể gửi cho họ một email có liên kết đến tệp .bat. Hành vi mong muốn là khi họ nhấp chuột phải vào tệp và nói Mở, họ sẽ nhận được một trong các hộp thoại UAC đó làm cho màn hình tối và buộc họ phải trả lời liệu họ có muốn cho phép ứng dụng chạy với tư cách quản trị viên hay không. Thay vào đó, họ chỉ thấy "Truy cập bị từ chối" trên cửa sổ dòng lệnh.

Điều này có thể làm khác đi?


2
Nếu bạn gặp phải điều này và, giống như tôi, rất vui khi sử dụng PowerShell, đừng bỏ lỡ phần mềm lót từ @ toster-cx. Hoàn hảo!
Michael Repucci

Câu trả lời:


352

Kịch bản này thực hiện các mẹo! Chỉ cần dán nó vào đầu tập tin bat của bạn. Nếu bạn muốn xem lại đầu ra của tập lệnh, hãy thêm lệnh "tạm dừng" ở cuối tệp bó của bạn.

CẬP NHẬT: Tập lệnh này hiện được chỉnh sửa một chút để hỗ trợ các đối số dòng lệnh và HĐH 64 bit.

Cảm ơn bạn Eneerge @ https://sites.google.com/site/eneerge/scripts/batchgotadmin

@echo off

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
    IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" (
>nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system"
) ELSE (
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.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"
    set params= %*
    echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    del "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------    
    <YOUR BATCH SCRIPT HERE>

22
Tôi ghét phải làm điều này vô nghĩa bẩn thỉu hàng loạt nhưng đôi khi bạn bị ép buộc và điều này làm việc rất tốt. Chúc mừng!
matt đốt

4
Phương pháp này không chuyển tiếp đối số. Bạn có biết làm thế nào mà có thể được thực hiện? Về cơ bản những gì tôi quan sát được là trên dòng đầu tiên% 1 có một số giá trị và trên dòng cuối cùng% 1 là null. Tôi cần chuyển tiếp các đối số.
ngạnh

3
Giống như một FYI, điều này được kiểm tra là hoạt động trong Windows 8 Embedded
Robert Snyder

6
Điều này ném máy của tôi vào một vòng tròn của các cửa sổ lệnh mở và đóng chéo trên màn hình. Cách duy nhất để ngăn chặn nó là xóa tệp bó gốc. Nó liên tục chạy tệp bó của tôi và viết tệp vbs. Lần đầu tiên nó xin phép, nhưng sau đó nó chỉ lặp.
TomDestry

2
Tôi gặp vấn đề chính xác giống như TomDestry với vòng lặp vô hạn và trả về mã 2. Đây là trên Windows 8.1. Tôi biết rằng nó đã hoạt động trên Windows 8.0 và không thể chắc chắn liệu đó là bản cập nhật 8.1 hay thứ gì khác gây ra sự cố. Giải pháp hiệu quả với tôi là không sử dụng cacls.exe (hoặc icacls), thay vào đó: phiên net> nul 2> & 1 NẾU ERRORLEVEL 1 goto UACPrompt ...
crig

55

Đây là một lớp lót tôi đã sử dụng:

@echo off
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)

echo main code here
pause

Ghi chú:

  • Chỉ được thử nghiệm trên windows 7 và 10, bạn có thể phải loay hoay với trích dẫn
  • Hiện tại không hỗ trợ chuyển các đối số

1
Nếu bạn biết có bao nhiêu thông số có thể có, bạn có thể truyền tham số bằng cách đưa chúng vào sau Thông số am_admin if not "%1"=="am_admin" (powershell start -verb runas '%0' 'am_admin "%~1" "%~2"' & exit)sẽ ở trên đó
Tony Brix

Cũng có thể sử dụng 'am_admin %*'để vượt qua mọi thứ, không chơi tốt với dấu ngoặc kép và dấu cách tho: / Bạn có thể sử dụng shifttheo đợt để bật đối số đầu tiên, do đó sửa tất cả các đối số ngoại trừ %0.
toster-cx

Đây là câu trả lời tốt, nhưng không nên được chấp nhận, bởi vì nó KHÔNG kiểm tra xem trên lần chạy đầu tiên, nó có được chạy với đặc quyền ADMIN hay không.
T.Todua

Để giữ thư mục làm việc thêm cd /D %~dp0sauif not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
Pedro Duarte

Câu trả lời tốt. Đơn giản chỉ hoạt động trong khi điều VB script tạo ra một vòng lặp vô hạn, ngay cả với quyền ghi cho% temp%.
Twonky

19

Đây là mã của tôi! Nó trông có vẻ lớn nhưng chủ yếu là các dòng bình luận (các dòng bắt đầu bằng: :).

Đặc trưng:

  • Chuyển tiếp đối số đầy đủ
  • Không thay đổi thư mục làm việc
  • Xử lý lỗi
  • Chấp nhận đường dẫn có dấu ngoặc đơn (ngoại trừ thư mục% TEMP%)
  • Hỗ trợ các đường dẫn UNC
  • Kiểm tra thư mục đã ánh xạ (Cảnh báo cho bạn nếu quản trị viên có thể truy cập ổ đĩa được ánh xạ)

  • Có thể được sử dụng làm thư viện bên ngoài (kiểm tra bài đăng của tôi tại chủ đề này: https://stackoverflow.com/a/30417025/4932683 )

  • Có thể được gọi khi / nếu cần bất cứ nơi nào trong mã của bạn

Chỉ cần đính kèm tệp này vào cuối tệp bó của bạn hoặc lưu nó dưới dạng thư viện (kiểm tra ở trên)

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:RequestAdminElevation FilePath %* || goto:eof
:: 
:: By:   Cyberponk,     v1.5 - 10/06/2016 - Changed the admin rights test method from cacls to fltmc
::          v1.4 - 17/05/2016 - Added instructions for arguments with ! char
::          v1.3 - 01/08/2015 - Fixed not returning to original folder after elevation successful
::          v1.2 - 30/07/2015 - Added error message when running from mapped drive
::          v1.1 - 01/06/2015
:: 
:: Func: opens an admin elevation prompt. If elevated, runs everything after the function call, with elevated rights.
:: Returns: -1 if elevation was requested
::           0 if elevation was successful
::           1 if an error occured
:: 
:: USAGE:
:: If function is copied to a batch file:
::     call :RequestAdminElevation "%~dpf0" %* || goto:eof
::
:: If called as an external library (from a separate batch file):
::     set "_DeleteOnExit=0" on Options
::     (call :RequestAdminElevation "%~dpf0" %* || goto:eof) && CD /D %CD%
::
:: If called from inside another CALL, you must set "_ThisFile=%~dpf0" at the beginning of the file
::     call :RequestAdminElevation "%_ThisFile%" %* || goto:eof
::
:: If you need to use the ! char in the arguments, the calling must be done like this, and afterwards you must use %args% to get the correct arguments:
::      set "args=%* "
::      call :RequestAdminElevation .....   use one of the above but replace the %* with %args:!={a)%
::      set "args=%args:{a)=!%" 
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1"
  if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information)
  :: UAC.ShellExecute only works with 8.3 filename, so use %~s1
  set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)
  :: Remove parenthesis from the temp filename
  set _FN=%_FN:(=%
  set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat"

  :: Test if we gave admin rights
  fltmc >nul 2>&1 || goto :_getElevation

  :: Elevation successful
  (if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% )) 
  :: Set ERRORLEVEL 0, set original folder and exit
  endlocal & CD /D "%~dp1" & ver >nul & goto:eof

  :_getElevation
  echo/Requesting elevation...
  :: Try to create %_vbspath% file. If failed, exit with ERRORLEVEL 1
  echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof) 
  echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath%
  :: Try to create %_batpath% file. If failed, exit with ERRORLEVEL 1
  echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof)
  echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%"

  :: Run %_vbspath%, that calls %_batpath%, that calls the original file
  %_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof)

  :: Vbscript has been run, exit with ERRORLEVEL -1
  echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Ví dụ về cách sử dụng nó

:EXAMPLE
@echo off

 :: Run this script with elevation
 call :RequestAdminElevation "%~dpfs0" %* || goto:eof

  echo/I now have Admin rights!
  echo/
  echo/Arguments using %%args%%:    %args%
  echo/Arguments using %%*: %*
  echo/%%1= %~1
  echo/%%2= %~2
  echo/%%3= %~3

  echo/
  echo/Current Directory: %CD%
  echo/
  echo/This file: %0
  echo/

pause &goto:eof

[here you paste the RequestAdminElevation function code]

Hoạt động tuyệt vời nhưng tôi đã phải thay đổi một dòng để làm cho nó hoạt động. Cái &fc;: 2>nultrong set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)đã đặt errorlevel thành 1. Tôi đã loại bỏ bit đó và nó hoạt động hoàn hảo. Tôi đang sử dụng Windows 10 Home.
Knyri

Thư mục% temp% của bạn có dấu ngoặc đơn trong đường dẫn của nó không? Chỉ trong trường hợp này, errorlevel 1 được cho là được đặt.
cyberponk

Không. Có cần nó fc;:kể từ khi nó đi: eof ngay sau đó? Tôi cũng không chắc tại sao một chút lại gây ra vấn đề, vì nó sẽ được thực thi.
Knyri

"fc;: 2> nul" có chủ ý đặt ERRORLEVEL 1 trước khi thoát, để báo hiệu lỗi. Bạn có thể vui lòng xóa @echo và chạy và gửi cho tôi đầu ra trong một tin nhắn riêng tư không? Cảm ơn!
cyberponk

Dù sao, các echo/%TEMP%| findstr /C:"(" >nulbài kiểm tra nếu có một biến (char trong %temp%môi trường yout và chỉ nên chạy phần sau khi &&if dương. Thật kỳ lạ tại sao (bài kiểm tra của bạn lại trở lại tích cực.
cyberponk

7

Một cách tiếp cận khác là

  • tạo một lối tắt cục bộ và đặt nó để gọi quyền của Quản trị viên [Thuộc tính, Nâng cao, Chạy với tư cách Quản trị viên]

và sau đó

  • gửi cho người dùng của bạn phím tắt [hoặc một liên kết đến phím tắt chứ không phải một liên kết đến tệp bó].

Denis

[Đã thêm sau đó - Có, tôi đã không nhận thấy ngày của chủ đề này.]


6

Giải pháp của Ben Gripka gây ra các vòng lặp vô hạn. Lô của anh ta hoạt động như thế này (mã giả):

IF "no admin privileges?"
    "write a VBS that calls this batch with admin privileges"
ELSE
    "execute actual commands that require admin privileges"

Như bạn có thể thấy, điều này gây ra một vòng lặp vô hạn, nếu VBS không yêu cầu đặc quyền quản trị viên.

Tuy nhiên, vòng lặp vô hạn có thể xảy ra, mặc dù quyền riêng tư của quản trị viên đã được yêu cầu thành công.

Việc kiểm tra tệp bó của Ben Gripka chỉ dễ bị lỗi. Tôi đã chơi xung quanh với lô và nhận thấy rằng các đặc quyền quản trị viên có sẵn mặc dù kiểm tra không thành công. Thật thú vị, kiểm tra hoạt động như mong đợi, nếu tôi bắt đầu tệp bó từ windows explorer, nhưng nó không hoạt động khi tôi khởi động nó từ IDE của mình.

Vì vậy, tôi đề nghị sử dụng hai tập tin lô riêng biệt. Cái đầu tiên tạo VBS gọi tệp bó thứ hai:

@echo off

echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"=""
echo UAC.ShellExecute "cmd.exe", "/c ""%~dp0\my_commands.bat"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"

"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"

Cái thứ hai, được đặt tên là "my_commands.bat" và nằm trong cùng thư mục với cái đầu tiên chứa các lệnh thực tế của bạn:

pushd "%CD%"
CD /D "%~dp0"
REM Your commands which require admin privileges here

Điều này gây ra không có vòng lặp vô hạn và cũng loại bỏ kiểm tra đặc quyền quản trị dễ bị lỗi.


Làm việc cho bạn? Đáng buồn cho tôi, điều này và tất cả những người khác ở đây và từ các chủ đề khác đều thất bại vì cùng một vấn đề cơ bản. Parm (hoặc lệnh) "runas" thất bại bất cứ khi nào Shell Object được tạo gián tiếp từ bên trong một chương trình khác. Chủ đề quan tâm ở đây .
Laurie Stearn

Làm việc cho tôi :)
Sritam Jagadev

6

Một giải pháp PowerShell khác ...

Đây không phải là về việc chạy một tập lệnh bó theo quản trị viên, mà là cách nâng cao một chương trình khác từ đợt ...

Tôi có một tập tin "gói" cho một exe. Chúng có cùng "tên tệp gốc", nhưng các phần mở rộng thay thế. Tôi có thể khởi chạy exe với tư cách quản trị viên và đặt thư mục làm việc thành thư mục chứa tập lệnh, với lời gọi powershell một dòng sau:

@powershell "Start-Process -FilePath '%~n0.exe' -WorkingDirectory '%~dp0' -Verb RunAs"

Thêm thông tin

Có rất nhiều Start-Processtùy chọn bổ sung mà bạn có thể áp dụng! Thủ tục thanh toán: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.man Quản lý / start-process? View = powershell-6

Lưu ý rằng tôi sử dụng @tiền tố. Điều đó tương đương với @echo offmột dòng. Tôi sử dụng %~n0ở đây để lấy "tên gốc" của tập lệnh bó, sau đó tôi ghép nối .exeđể chỉ ra nó là nhị phân phụ. Việc sử dụng %~dp0cung cấp đường dẫn đầy đủ đến thư mục mà lô nằm trong đó. Và, tất nhiên, các -Verb RunAsthông số cung cấp độ cao .


4

Tôi biết đây không phải là giải pháp cho OP, nhưng vì tôi chắc chắn có nhiều trường hợp sử dụng khác ở đây, tôi nghĩ tôi sẽ chia sẻ.

Tôi đã gặp vấn đề với tất cả các ví dụ mã trong các câu trả lời này nhưng sau đó tôi thấy: http://www.robotronic.de/runasspcEn.html

Nó không chỉ cho phép bạn chạy với tư cách quản trị viên, nó kiểm tra tệp để đảm bảo nó không bị giả mạo và lưu trữ thông tin cần thiết một cách an toàn. Tôi sẽ thừa nhận nó không phải là công cụ rõ ràng nhất để tìm ra cách sử dụng nhưng đối với những người trong chúng ta viết mã thì nó đủ đơn giản.


3

@echo offtitlecó thể đến trước mã này:

net session>nul 2>&1
if %errorlevel%==0 goto main
echo CreateObject("Shell.Application").ShellExecute "%~f0", "", "", "runas">"%temp%/elevate.vbs"
"%temp%/elevate.vbs"
del "%temp%/elevate.vbs"
exit

:main
    <code goes here>
exit

Rất nhiều câu trả lời khác là quá mức nếu bạn không cần phải lo lắng về những điều sau đây:

  • Thông số
  • Thư mục làm việc ( cd %~dp0sẽ thay đổi thành thư mục chứa tệp bó)

3
@echo off 
Net session >nul 2>&1 || (PowerShell start -verb runas '%~0' &exit /b)
Echo Administrative privileges have been got. & pause

Các hoạt động trên trên Windows 10 Phiên bản 1903 của tôi


1

Vì tôi gặp rắc rối với tập lệnh này xuất hiện một dấu nhắc lệnh mới tự chạy lại, trong vòng lặp vô hạn (sử dụng Win 7 Pro), tôi khuyên bạn nên thử một cách tiếp cận khác: Làm cách nào tôi có thể tự động nâng cao tệp bó của mình, để nó yêu cầu Quyền quản trị viên UAC nếu được yêu cầu?

Hãy cẩn thận, bạn phải thêm phần này vào cuối tập lệnh, như đã nêu trong một chỉnh sửa, để bạn quay lại thư mục tập lệnh sau khi các đặc quyền được nâng lên: cd / d% ~ dp0


Kiểm tra câu trả lời của tôi cho câu hỏi này. Nó xử lý tất cả những vấn đề này.
cyberponk

1

Dựa trên bài đăng của toster-cx và các bài viết thú vị khác trên trang này, tôi đã hiểu rõ hơn về cách định cấu hình và giải quyết vấn đề của mình. Tôi gặp vấn đề tương tự khi tôi ước rằng tiện ích Disk Cleanup chạy mỗi tuần hai lần vào thứ Hai và thứ Năm trong giờ ăn trưa (giả sử là 2 giờ chiều). Tuy nhiên, điều này đòi hỏi quyền nâng cao.

Chia sẻ tệp bó có thể giúp những người mới bắt đầu như tôi -

@echo off
echo  Welcome to scheduling 'PC Maintenance Activity'
ping localhost -n 3 >nul
echo -- Step - 1 of 3 : Please give 'Admin' rights on next screen
ping localhost -n 5 >nul
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit)
cls
echo -- Step - 2 of 3 : In next screen, select temp areas for cleaning 
during routine scheduled activity
ping localhost -n 3 >nul
C:\Windows\System32\cleanmgr.exe /sageset:112
cls
echo    Now scheduling maintenance activity...
SchTasks /Create /SC WEEKLY /D MON,THU /TN PC_Cleanup /TR 
"C:\Windows\System32\cleanmgr.exe "/sagerun:112 /ST 14:00

cls

echo                         -- Thanks for your co-operation --
echo                    -- Maintenance activity is scheduled for --
echo                       -- Every Monday and Thursday at 2 pm --

ping localhost -n 10 >nul

Cảm ơn rất nhiều về diễn đàn này và Rems POST tại đây [ https://www.petri.com/forums/forum/windows-scripting/general-scripting/32313-scht task -exe-news-to-pass-parameter-to-script ] [1]

Bài đăng của ông đã giúp cấu hình đối số tùy chọn trong khi lập lịch tác vụ.


1

Ngoài ra còn có truy vấn FSUTIL từ bài đăng này cũng được liên kết tại ss64.com có mã sau:

@Echo Off
Setlocal
:: First check if we are running As Admin/Elevated
FSUTIL dirty query %SystemDrive% >nul
if %errorlevel% EQU 0 goto START

::Create and run a temporary VBScript to elevate this batch file
   Set _batchFile=%~f0
   Set _Args=%*
   :: double up any quotes
   Set _batchFile=""%_batchFile:"=%""
   Set _Args=%_Args:"=""%

   Echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\~ElevateMe.vbs"
   Echo UAC.ShellExecute "cmd", "/c ""%_batchFile% %_Args%""", "", "runas", 1 >> "%temp%\~ElevateMe.vbs"

   cscript "%temp%\~ElevateMe.vbs" 
   Exit /B

:START
:: set the current directory to the batch file location
cd /d %~dp0
:: Place the code which requires Admin/elevation below
Echo We are now running as admin [%1] [%2]
pause

Chừng nào FSUTIL còn tồn tại, đó là một sự thay thế đáng tin cậy.


0

Bạn không thể yêu cầu quyền quản trị từ một tệp bó, nhưng bạn có thể viết tập lệnh máy chủ kịch bản windows trong% temp% và chạy nó (và đến lượt nó thực thi lô của bạn với tư cách quản trị viên) Bạn muốn gọi phương thức ShellExecute trong Shell. Đối tượng ứng dụng với "runas" là động từ


0

Sử dụng mshtađể nhắc về quyền quản trị:

@echo off
net session >nul 2>&1 && goto :admintasks
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
exit /b
:admintasks
rem ADMIN TASKS HERE

Hoặc, sử dụng powershell:

powershell -c Start-Process "%~nx0" -Verb runas

-5

sử dụng lệnh runas. Nhưng, tôi không nghĩ rằng bạn có thể gửi email một tệp .bat dễ dàng.


6
Câu trả lời này không chính xác. Các runaslệnh không thể được sử dụng để kích cao.
Bill_Stewart
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.