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 từ quyền quản trị viên UAC nếu được yêu cầu?


209

Tôi muốn tập tin lô của tôi chỉ chạy cao. Nếu không tăng, cung cấp tùy chọn cho người dùng khởi chạy lại lô theo độ cao.

Tôi đang viết một tệp bó để đặt biến hệ thống, sao chép hai tệp vào vị trí Tệp chương trình và khởi động trình cài đặt trình điều khiển. Nếu người dùng Windows 7 / Windows Vista ( bật UAC và ngay cả khi họ là quản trị viên cục bộ) chạy nó mà không cần nhấp chuột phải và chọn "Chạy với tư cách Quản trị viên", họ sẽ nhận được 'Truy cập từ chối' sao chép hai tệp và viết biến hệ thống .

Tôi muốn sử dụng một lệnh để tự động khởi động lại lô theo mức cao nếu người dùng thực tế là một quản trị viên. Mặt khác, nếu họ không phải là quản trị viên, tôi muốn nói với họ rằng họ cần đặc quyền của quản trị viên để chạy tệp bó. Tôi đang sử dụng xcopy để sao chép các tệp và REG ADD để ghi biến hệ thống. Tôi đang sử dụng các lệnh đó để đối phó với các máy Windows XP có thể. Tôi đã tìm thấy những câu hỏi tương tự về chủ đề này, nhưng không có gì liên quan đến việc khởi chạy lại một tập tin theo lô.


2
Kiểm tra những gì tôi đã đăng - bạn không cần bất kỳ công cụ bên ngoài nào, tập lệnh sẽ tự động kiểm tra quyền quản trị và tự động nâng cao nếu cần.
Matt

1
Vui lòng xem xét nếu câu trả lời của Matt sẽ là câu trả lời? Có vẻ như vậy với tôi.
akauppi


Vui lòng xem các gợi ý Windows 10 mới trong phần bình luận của tập lệnh bó tôi đã đăng.
Matt

4
Từ cmd : @powershell Start-Process cmd -Verb runas. Từ Powershell chỉ cần thả @powershell. Điều này bắt đầu cmd với quyền nâng cao.
BrunoLM

Câu trả lời:


20

Bạn có thể có lệnh gọi chính nó với tùy chọn của psexec-h để chạy cao.

Tôi không chắc chắn làm thế nào bạn có thể phát hiện xem nó có chạy ở độ cao hay không ... có thể thử lại với perms nâng cao chỉ khi có lỗi Truy cập bị từ chối?

Hoặc, bạn có thể chỉ cần có các lệnh cho xcopyreg.exeluôn được chạy cùng psexec -h, nhưng sẽ gây khó chịu cho người dùng cuối nếu họ cần nhập mật khẩu của họ mỗi lần (hoặc không an toàn nếu bạn đưa mật khẩu vào tập lệnh) ...


10
Cảm ơn vì sự trả lời. Thật không may, tôi không nghĩ rằng tôi có thể sử dụng bất cứ thứ gì ngoài công cụ Windows Vista / 7 vì nó sẽ được cung cấp cho khách hàng bên ngoài văn phòng của tôi. Tôi không nghĩ rằng tôi có thể phân phối hợp pháp PSExec.
PDixon724

2
Vâng, tôi nghĩ bạn đã đúng về điều đó - mặc dù PSExec hiện là công cụ của Microsoft (vì họ đã mua các kẻ
Sysiternals

2
Tôi nghĩ rằng lựa chọn của tôi là khá hạn chế. Nếu tôi biết cách viết mã trong VB, tôi có thể biến nó thành một exe với bảng kê khai của quản trị viên, nhưng tôi thậm chí sẽ không biết bắt đầu từ đâu. Tôi đoán tôi sẽ chỉ cảnh báo vào đầu đợt để chạy với tư cách quản trị viên nếu họ đang chạy Windows Vista / 7. Cảm ơn tất cả.
PDixon724

1
Một công cụ của bên thứ 3 khác có thể tự do phân phối lại và dễ tích hợp và học hỏi là AutoIt ; trang này trình bày cách tập lệnh yêu cầu các đặc quyền nâng cao.
ewall

4
psexec -hkhông hoạt động: 'Không thể cài đặt dịch vụ PSEXESVC: Truy cập bị từ chối.'. Bạn cần phải có quyền quản trị để chạy psexec.
Nicolas

319

Có một cách dễ dàng mà không cần sử dụng công cụ bên ngoài - nó chạy tốt với Windows 7, 8, 8.1 và 10 và cũng tương thích ngược (Windows XP không có bất kỳ UAC nào, do đó không cần độ cao - trong đó trường hợp kịch bản chỉ tiến hành).

Kiểm tra mã này (Tôi lấy cảm hứng từ mã do NIronwolf đăng trong chuỗi Batch File - "Truy cập bị từ chối" trên Windows 7? ), Nhưng tôi đã cải thiện nó - trong phiên bản của tôi không có thư mục nào được tạo và xóa kiểm tra các đặc quyền của quản trị viên):

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

Kịch bản lợi dụng thực tế NET FILEđòi hỏi đặc quyền của quản trị viên và trả về errorlevel 1nếu bạn không có nó. Độ cao đạt được bằng cách tạo một tập lệnh khởi chạy lại tệp bó để có được các đặc quyền. Điều này khiến Windows xuất hiện hộp thoại UAC và yêu cầu bạn cung cấp tài khoản và mật khẩu quản trị viên.

Tôi đã thử nghiệm nó với Windows 7, 8, 8.1, 10 và với Windows XP - nó hoạt động tốt cho tất cả. Ưu điểm là, sau điểm bắt đầu, bạn có thể đặt bất cứ thứ gì yêu cầu đặc quyền của quản trị viên hệ thống, ví dụ, nếu bạn có ý định cài đặt lại và chạy lại dịch vụ Windows cho mục đích gỡ lỗi (giả sử mypackage.msi là gói cài đặt dịch vụ) :

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

Nếu không có tập lệnh nâng cao đặc quyền này, UAC sẽ hỏi bạn ba lần về mật khẩu và người dùng quản trị viên của bạn - bây giờ bạn chỉ được hỏi một lần khi bắt đầu và chỉ khi được yêu cầu.


Nếu tập lệnh của bạn chỉ cần hiển thị thông báo lỗi và thoát nếu không có bất kỳ đặc quyền quản trị viên nào thay vì tự động nâng cao, thì điều này thậm chí còn đơn giản hơn: Bạn có thể đạt được điều này bằng cách thêm vào phần sau của tập lệnh:

@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 ...

Bằng cách này, người dùng phải nhấp chuột phải và chọn "Chạy với tư cách quản trị viên" . Kịch bản sẽ tiến hành sau REMcâu lệnh nếu phát hiện quyền quản trị viên, nếu không thì thoát với lỗi. Nếu bạn không yêu cầu PAUSE, chỉ cần loại bỏ nó. Quan trọng: NET FILE [...] EXIT /D) phải trên cùng một dòng. Nó được hiển thị ở đây trong nhiều dòng để dễ đọc hơn!


Trên một số máy, tôi đã gặp phải sự cố đã được giải quyết trong phiên bản mới ở trên. Một là do xử lý trích dẫn kép khác nhau và vấn đề còn lại là do UAC bị vô hiệu hóa (được đặt ở mức thấp nhất) trên máy Windows 7, do đó tập lệnh tự gọi đi gọi lại.

Bây giờ tôi đã sửa lỗi này bằng cách tước các trích dẫn trong đường dẫn và thêm lại chúng sau đó và tôi đã thêm một tham số bổ sung được thêm vào khi tập lệnh khởi chạy lại với quyền nâng cao.

Các trích dẫn kép được loại bỏ bằng cách sau đây (chi tiết ở đây ):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

Sau đó bạn có thể truy cập đường dẫn bằng cách sử dụng !batchPath!. Nó không chứa bất kỳ dấu ngoặc kép nào, vì vậy có thể an toàn để nói "!batchPath!"sau trong tập lệnh.

Dòng

if '%1'=='ELEV' (shift & goto gotPrivileges)

kiểm tra xem tập lệnh đã được tập lệnh VBScript gọi để nâng cao quyền hay chưa, do đó tránh được sự thu hồi vô tận. Nó loại bỏ tham số bằng cách sử dụng shift.


Cập nhật:

  • Để tránh phải đăng ký .vbstiện ích mở rộng trong Windows 10 , tôi đã thay thế dòng này
    "%temp%\OEgetPrivileges.vbs"
    bằng
    "%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
    đoạn script trên; cũng được thêm vào cd /d %~dp0theo đề xuất của Stephen (câu trả lời riêng) và Tomáš Zato (bình luận) để đặt thư mục script làm mặc định.

  • Bây giờ kịch bản vinh danh các tham số dòng lệnh được truyền cho nó. Cảm ơn jxmallet, TanisDLJ và Peter Mortensen đã quan sát và truyền cảm hứng.

  • Theo gợi ý của Artjom B., tôi đã phân tích nó và đã thay thế SHIFTbằng SHIFT /1, nó giữ nguyên tên tệp cho %0tham số

  • Thêm del "%temp%\OEgetPrivileges_%batchName%.vbs"vào :gotPrivilegesphần để làm sạch (như MLT gợi ý). Đã thêm %batchName%để tránh tác động nếu bạn chạy các lô khác nhau song song. Lưu ý rằng bạn cần sử dụng forđể có thể tận dụng các hàm chuỗi nâng cao, chẳng hạn như %%~nk, chỉ trích xuất tên tệp.

  • Cấu trúc tập lệnh được tối ưu hóa, các cải tiến (biến được thêm vbsGetPrivilegeshiện được tham chiếu ở mọi nơi cho phép dễ dàng thay đổi đường dẫn hoặc tên của tệp, chỉ xóa .vbstệp nếu cần nâng cao lô)

  • Trong một số trường hợp, một cú pháp gọi khác nhau được yêu cầu cho độ cao. Nếu tập lệnh không hoạt động, hãy kiểm tra các tham số sau:
    set cmdInvoke=0
    set winSysFolder=System32
    Thay đổi tham số thứ 1 thành set cmdInvoke=1và kiểm tra xem điều đó đã khắc phục sự cố chưa. Nó sẽ thêm cmd.exevào kịch bản thực hiện độ cao.
    Hoặc cố gắng thay đổi tham số thứ 2 thành winSysFolder=Sysnative, điều này có thể giúp ích (nhưng trong hầu hết các trường hợp không bắt buộc) trên các hệ thống 64 bit. (ADBailey đã báo cáo điều này). "Sysnative" chỉ được yêu cầu để khởi chạy các ứng dụng 64 bit từ máy chủ tập lệnh 32 bit (ví dụ: quy trình xây dựng Visual Studio hoặc gọi tập lệnh từ ứng dụng 32 bit khác).

  • Để làm rõ hơn về cách các tham số được diễn giải, tôi hiện đang hiển thị nó như thế nào P1=value1 P2=value2 ... P9=value9. Điều này đặc biệt hữu ích nếu bạn cần kèm theo các tham số như đường dẫn trong dấu ngoặc kép, vd "C:\Program Files".

  • Nếu bạn muốn gỡ lỗi tập lệnh VBS, bạn có thể thêm //Xtham số vào WScript.exe làm tham số đầu tiên, như được đề xuất ở đây (nó được mô tả cho CScript.exe, nhưng cũng hoạt động với WScript.exe).

Liên kết hữu ích:


9
Câu trả lời tuyệt vời, mặc dù điều đó làm tôi ngạc nhiên một chút rằng bạn phải làm tất cả những điều đó để làm một cái gì đó rõ ràng là cần thiết trong một số trường hợp.
jcoder

50
Thật vậy, một lệnh như ELEVATE rõ ràng bị thiếu trong ngôn ngữ lô Windows.
Matt

2
Có lẽ nó dễ dàng hơn với powershell dường như là làn đường kịch bản được phê duyệt cho những thứ phức tạp hơn, nhưng tôi chưa bao giờ bận tâm tìm hiểu nó cho đến nay :(
jcoder

1
Cú pháp trong powershell hoàn toàn khác nhau (cú pháp động từ-danh từ), nhưng nó cho phép bạn gọi các cụm .NET dễ dàng. Nhưng nó khó hơn một chút để xử lý nó (ký tập lệnh, v.v.).
Matt

2
@Matt Bạn có thể kiểm tra xem có một số sự thật đằng sau chỉnh sửa bị từ chối này trong câu trả lời của bạn không?
Artjom B.

41

Như jcoder và Matt đã đề cập, PowerShell đã làm cho nó trở nên dễ dàng và thậm chí nó có thể được nhúng vào tập lệnh bó mà không tạo tập lệnh mới.

Tôi đã sửa đổi kịch bản của Matt:

:: 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
Bạn đã đúng, nếu PowerShell được cài đặt, bạn có thể sử dụng nó để chạy tệp bó với độ cao (cảm ơn vì đoạn mã!). Và vâng, nhãn là không cần thiết. Cảm ơn bạn đã gợi ý, nó đáng giá +1 ... :-)
Matt

2
Khi được gọi từ cmd Powershell.exe không có tùy chọn -verb runas. Nó tồn tại nếu bạn đã có trong PowerShell.
Adil Hindistan

1
Tôi thực sự thích giải pháp này, làm việc tuyệt vời cho tôi. Trên Windows 8.1 tôi đã yêu cầu nhãn: gotPriv đặc quyền để nó hoạt động.
ShaunO

Tôi đang gặp sự cố nếu tệp bó này ở xa trên đường dẫn UNC.
Ryan Beesley

Tôi đã thêm thư mục thay đổi khi bắt đầu, đơn giản hóa luồng và làm sạch một chút. Không thể thay đổi thư mục công việc thông qua WorkingDirectorytham số Start-Processvì lý do bảo mật trong runascác quy trình
ceztko

28

Tôi đang sử dụng câu trả lời tuyệt vời của Matt, nhưng tôi đang thấy sự khác biệt giữa các hệ thống Windows 7 và Windows 8 của tôi khi chạy các tập lệnh nâng cao.

Khi tập lệnh được nâng lên trên Windows 8, thư mục hiện tại được đặt thành C:\Windows\system32. May mắn thay, có một cách giải quyết dễ dàng bằng cách thay đổi thư mục hiện tại thành đường dẫn của tập lệnh hiện tại:

cd /d %~dp0

Lưu ý: Sử dụng cd /dđể đảm bảo ký tự ổ đĩa cũng được thay đổi.

Để kiểm tra điều này, bạn có thể sao chép phần sau vào tập lệnh. Chạy bình thường trên một trong hai phiên bản để xem kết quả tương tự. Chạy với tư cách Quản trị viên và thấy sự khác biệt trong 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
Gợi ý tốt, Stephen. Vì vậy, tập lệnh nên kết thúc bằng cd %~dp0để giữ lại đường dẫn hiện tại của nó (Tôi giả sử điều này cũng hoạt động trong Win7, do đó, cùng một lệnh có thể được sử dụng mặc dù chỉ cần cho Win8 +). +1 cho việc này!
Matt

2
Lưu ý rằng điều này cũng được yêu cầu trên hệ thống của tôi chạy Windows 7.
meh-uk

1
hoặc sử dụng pushd %~dp0thay thế ... tại sao? bởi vìpopd
Jaroslav Záruba

27

Tôi làm theo cách này:

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

Cách này đơn giản và chỉ sử dụng các lệnh mặc định của windows. Thật tuyệt nếu bạn cần phân phối lại tệp bó.

CD /d %~dp0Đặt thư mục hiện tại vào thư mục hiện tại của tệp (nếu chưa có, bất kể ổ đĩa chứa tệp là gì, nhờ vào /dtùy chọn).

%~nx0 Trả về tên tệp hiện tại có phần mở rộng (Nếu bạn không bao gồm phần mở rộng và có một exe có cùng tên trên thư mục, nó sẽ gọi exe).

Có rất nhiều câu trả lời trên bài đăng này tôi thậm chí không biết liệu câu trả lời của mình sẽ được nhìn thấy hay không.

Dù sao, tôi thấy cách này đơn giản hơn các giải pháp khác được đề xuất cho các câu trả lời khác, tôi hy vọng nó sẽ giúp được ai đó.


4
cd% ~ dp0 sẽ không hoạt động trên các ổ đĩa Mạng, thay vào đó, hãy sử dụng Pushd% ~ dp0.
Stavm

1
Tôi yêu sự đơn giản của câu trả lời này. Và cuối cùng là một lý do để sử dụng Jscript!
Joe Coder

1
Ma thuật! Cảm ơn rât nhiều.
Daniele Orlando

1
@Wolf Tôi đã gõ một câu trả lời lớn chỉ để nhận ra tôi hiểu sai về bạn ... Tôi hiểu ý của bạn bây giờ. Tôi sẽ chỉnh sửa nó để bao gồm /d. Cảm ơn bạn :) (PS: Nghệ sĩ piano cũng ở đây!)
Matheus Rocha

1
Điều này hoạt động rất tốt, nhưng có thể là một ý tưởng tốt để di chuyển cdlệnh đến điểm bắt đầu (điều này đảm bảo rằng đường dẫn cũng có sẵn cho tập lệnh nâng cao - nếu không thì tập lệnh nâng cao chỉ chạy từ system32). Bạn cũng nên chuyển hướng lệnh net sang nul để ẩn đầu ra của nó:net session >nul 2>&1
Nulano

23

Matt có một câu trả lời tuyệt vời, nhưng nó loại bỏ bất kỳ đối số nào được chuyển đến kịch bản. Đây là sửa đổi của tôi giữ cho các đối số. Tôi cũng đã kết hợp sửa lỗi của Stephen cho vấn đề thư mục làm việc trong 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
Đây là một câu trả lời hữu ích. Tuy nhiên trong ECHO UAC.ShellExecute....dòng, "batchArgs!"sẽ không mở rộng biến. Sử dụng "!batchArgs!". Chỉnh sửa của tôi đã bị từ chối, vì vậy tôi nhận xét.
hành tây bay

1
@fliedonion cũng phát hiện ra! Tôi không chắc tại sao chỉnh sửa của bạn bị từ chối vì đó chắc chắn là một lỗi đánh máy và bản sửa lỗi của bạn hoạt động. Tự thực hiện thay đổi và thử nghiệm nó trên Win 8.1. Bây giờ để tìm tất cả các tập lệnh nơi tôi sử dụng mã này ....
jxmallett

2
Kịch bản bị test.bat "a thing"hỏng khi sử dụng các đối số được trích dẫn, như hoặc "test script.bat" arg1 arg2. Tất cả đã được sửa.
jxmallett

Tôi đã quản lý để phá vỡ nó (do lỗi của tôi: chạy tập lệnh từ ổ đĩa mạng được ánh xạ, vì quản trị viên và người dùng bình thường không có ánh xạ giống nhau). Tuy nhiên: có cách nào để xem đầu ra không? Đối với tôi, tôi đã phải tìm .vbs và thay đổi / c thành a / K và sau đó nhìn thấy nó bằng tay.
Andreas Reiff

21

Tôi sử dụng PowerShell để khởi chạy lại tập lệnh nâng cao nếu không. Đặt những dòng này ở đầu kịch bản của bạn.

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

Tôi đã sao chép phương thức 'tên mạng' từ câu trả lời của @ Matt. Câu trả lời của ông là tài liệu tốt hơn nhiều và có thông báo lỗi và tương tự. Điều này có lợi thế là PowerShell đã được cài đặt và có sẵn trên Windows 7 trở lên. Không có tệp VBScript (* .vbs) tạm thời và bạn không phải tải xuống các công cụ.

Phương pháp này sẽ hoạt động mà không cần bất kỳ cấu hình hoặc thiết lập nào, miễn là các quyền thực thi PowerShell của bạn không bị khóa.


khi cung cấp một danh sách các đối số được phân tách khoảng trắng được bao quanh bởi các dấu ngoặc kép để làm cho nó được coi là một, /c %~fnx0 %*'phần này dường như để lại mọi phần bên cạnh phần đầu tiên. Ví dụ: test.bat "arg1 arg2 arg3"chỉ từ arg1 được chuyển tiếp
Nicolas Mommaerts

Dường như không có vấn đề gì, Quá trình bắt đầu loại bỏ tất cả các trích dẫn kép trong danh sách đối số ..
Nicolas Mommaerts

Làm việc cho tôi! Tôi đang sử dụng nó cho netsh int set int %wifiname% Enable/Disable.
Marslo

2
Tôi đã có cùng một vấn đề như Nicolas Mommaerts ở trên. Tôi không hiểu tại sao nó hoạt động (loại sửa chữa tốt nhất), nhưng các cách sau hoạt động như vậy (lưu ý tất cả các dấu ngoặc kép phụ ở cuối): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
trận động đất

Một vấn đề khác (bất tiện) là tập lệnh tạm dừng (chờ đầu vào của người dùng) nếu dịch vụ máy chủ không chạy (tôi đã vô hiệu hóa vì lý do). Tôi thường kiểm tra sự cho phép của quản trị viên bằng cách cố gắng ghi vào vị trí tệp HOSTS , nhưng có lẽ tốt hơn để gọi lệnh powershell -Verb runas , thay vì dựa vào các dịch vụ windows được kích hoạt hoặc thử ghi tệp.
script'n'code

15

Đối với một số chương trình, thiết lập __COMPAT_LAYERbiến môi trường siêu bí mật RunAsInvoker sẽ hoạt động. Hãy kiểm tra điều này:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Mặc dù như thế này sẽ không có UAC nhắc nhở người dùng sẽ tiếp tục mà không có quyền quản trị.


1
Liên kết đến trang web Microsoft không còn hoạt động, vì vậy tôi đã thay đổi nó thành nội dung trên archive.org. Nếu bất cứ ai cũng có thể tìm thấy một liên kết hoạt động đến nội dung trên trang web của Microsoft, nhưng tất cả các phương tiện, vui lòng cập nhật nó vào đó.
RockPaperLizard

1
nó vẫn ở trạng thái toàn vẹn trung bình không tăng , vì vậy bạn không thể chỉnh sửa HKLM regedit. Nó chỉ bỏ qua uac.
HackingAddict1337

5

Tôi đã dán cái này vào đầu kịch bản:

:: 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
Tôi thích xử lý arg trong kịch bản của bạn. Nhưng lưu ý rằng caclskhông được dùng trong Windows 7 và các phiên bản Windows mới hơn.
Matt

Fsutil bẩn thậm chí còn tốt hơn
Wolf

1
Bạn có biết rằng dòng pushd "%CD%"lưu thư mục làm việc hiện tại và thay đổi thư mục làm việc hiện tại?
Sói

3

Đó là năm 2020 và tại sao windows chưa có công cụ sudo?

Vì vậy, tôi đã viết gsudo, một sudocho các cửa sổ : nó nâng lên trong bảng điều khiển hiện tại (không chuyển ngữ cảnh sang cửa sổ mới), với bộ đệm thông tin xác thực (cửa sổ bật lên UAC giảm) và cũng nâng cao các lệnh PowerShell .

Nó cho phép nâng cao các lệnh yêu cầu đặc quyền của quản trị viên hoặc toàn bộ lô, nếu bạn muốn:

Chỉ cần chuẩn bị gsudo trước bất cứ điều gì cần chạy cao.

Ví dụ tệp bó nâng cao chính nó:

@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

Xem gsudo trong hành động: bản demo gsudo

Tải về:


Mát mẻ. Cảm ơn. Nó hoạt động trên phiên bản nào của Windows?
RockPaperLizard

Bộ kiểm tra chạy trên Server 2019 và hộp dev cục bộ của tôi là Windows 10 1909. Xin lỗi tôi chưa kiểm tra khả năng tương thích với các HĐH cũ khác.
Gerardo Grignoli

Cảm ơn Gerardo. Nếu bất cứ ai thử nó trên các phiên bản Windows khác, xin vui lòng gửi kết quả của bạn.
RockPaperLizard

Tôi vừa thử nghiệm gsudo v0.7 trên Windows 8.1 và đã hoạt động. Nó không tầm thường để cài đặt .Net Framework 4.6ở đó. May mắn choco install dotnet4.6.2mang lại một số phụ thuộc khó có được. Sau đó, đã gsudo config Prompt "$p# "khắc phục sự cố với ConHosthiển thị dấu nhắc sai (ký tự thoát chuỗi thay vì sắc nét đỏ). @RockPaperLizard
Gerardo Grignoli

Cảm ơn rất nhiều Gerardo. Nó có thể được biên dịch lại để hoạt động với bất kỳ phiên bản nào của .Net Framework trước 4.6 hay không, hay nó phụ thuộc vào một số chức năng cụ thể của 4.6?
RockPaperLizard

2

Mặc dù không thể áp dụng trực tiếp cho câu hỏi này, vì nó muốn một số thông tin cho người dùng, google đã đưa tôi đến đây khi tôi muốn chạy tệp .bat của mình được nâng lên từ trình lập lịch tác vụ.

Cách tiếp cận đơn giản nhất là tạo một lối tắt đến tệp .bat, vì đối với một phím tắt, bạn có thể đặt Run as administratortrực tiếp từ các thuộc tính nâng cao.

Chạy phím tắt từ trình lập lịch tác vụ, chạy tệp .bat nâng cao.


0

Sử dụng quyền hạn.

Nếu tệp cmd dài, tôi sử dụng tệp đầu tiên để yêu cầu độ cao và sau đó gọi tệp đang thực hiện công việc thực tế.

Nếu tập lệnh là một lệnh đơn giản, mọi thứ có thể vừa với một tệp cmd. Đừng quên bao gồm đường dẫn trên tệp script.

Bản mẫu:

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

Ví dụ 1:

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

Ví dụ 2:

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

0

Thử cái này:

@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

Nếu bạn cần thông tin về tệp bó đó, hãy chạy Đoạn mã 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

Giải pháp sau đây là sạch sẽ và hoạt động hoàn hảo.

  1. Tải xuống tệp zip Nâng cao từ https://www.winability.com/doad/Elevate.zip

  2. Bên trong zip bạn nên tìm hai tập tin: Elevate.exe và Elevate64.exe. (Cái sau là một trình biên dịch 64 bit gốc, nếu bạn yêu cầu điều đó, mặc dù phiên bản 32 bit thông thường, Elevate.exe, sẽ hoạt động tốt với cả phiên bản Windows 32 và 64 bit)

  3. Sao chép tập tin Elevate.exe vào một thư mục nơi Windows luôn có thể tìm thấy nó (chẳng hạn như C: / Windows). Hoặc tốt hơn bạn có thể sao chép trong cùng một thư mục nơi bạn dự định giữ tệp dơi của mình.

  4. Để sử dụng nó trong một tệp bó, chỉ cần thêm vào lệnh bạn muốn thực thi với tư cách quản trị viên bằng lệnh nâng cao, như sau:

 elevate net start service ...

2
Lệnh đó chỉ mở một hộp thoại để hỏi người dùng xem lệnh này có được phép thực thi không. Vì vậy, bạn không thể sử dụng lệnh này trong một đợt, những gì nên chạy mà KHÔNG CÓ tương tác người dùng.
Radon8472

Nếu có thể nâng cao mà KHÔNG có sự tương tác của người dùng thì đó sẽ là một lỗ hổng bảo mật rất lớn, phải không? Mọi vi-rút sẽ bắt đầu sử dụng phương pháp đó để tự nâng cao mà không cần sự chấp thuận của người dùng.
Andrei Belogortseff
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.