外部ツールを使用せずに簡単な方法があります-それはWindows7、8、8.1、10、および11で正常に動作し、下位互換性もあります(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=%~dpnx0"
rem this works also from cmd shell, other than %~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ダイアログを表示し、管理者アカウントとパスワードの入力を求めます。
私はそれをWindows7、8、8.1、10、11とWindowsXPでテストしました-それはすべてのためにうまく働きます。利点は、開始点の後に、システム管理者権限が必要なものをすべて配置できることです。たとえば、デバッグ目的でWindowsサービスを再インストールして再実行する場合(mypackage.msiがサービスインストーラーパッケージであると想定)。 :
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
この特権昇格スクリプトがないと、UACは管理者ユーザーとパスワードを3回要求します。これで、最初に1回だけ、必要な場合にのみ要求されます。
スクリプトでエラーメッセージを表示し、自動昇格ではなく管理者権限がない場合に終了する必要がある場合、これはさらに簡単です。スクリプトの先頭に次を追加することで、これを実現できます。
@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)
同じ行にある必要があります。読みやすくするために、ここでは複数行で表示されます。
一部のマシンでは、上記の新しいバージョンですでに解決されている問題が発生しました。1つは、二重引用符の処理が異なるためであり、もう1つは、Windows 7マシンでUACが無効になっている(最低レベルに設定されている)ため、スクリプトが何度も自分自身を呼び出すためです。
パス内の引用符を削除して後で再度追加することでこれを修正しました。また、スクリプトが昇格された権限で再起動したときに追加されるパラメーターを追加しました。
二重引用符は次のように削除されます(詳細はこちら)。
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
その後、を使用してパスにアクセスできます!batchPath!
。"!batchPath!"
二重引用符は含まれていないため、スクリプトの後半で安全に言うことができます。
この線
if '%1'=='ELEV' (shift & goto gotPrivileges)
スクリプトがVBScriptスクリプトによって既に呼び出されているかどうかをチェックして、権限を昇格させ、無限の再帰を回避します。を使用してパラメータを削除しますshift
。
アップデート:
Windows 10.vbs
で拡張機能を登録する必要をなくすために、上記のスクリプトの行をに置き換えました。また、Stephen(別の回答)とTomášZato(コメント)によって提案されたように、スクリプトディレクトリをデフォルトとして設定するために追加されました。
"%temp%\OEgetPrivileges.vbs"
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
cd /d %~dp0
これで、スクリプトは渡されるコマンドラインパラメータを尊重します。観察とインスピレーションを与えてくれたjxmallet、TanisDLJ、PeterMortensenに感謝します。
Artjom B.のヒントによると、私はそれを分析し、パラメーターのファイル名を保持するにSHIFT
置き換えました。SHIFT /1
%0
del "%temp%\OEgetPrivileges_%batchName%.vbs"
クリーンアップする:gotPrivileges
セクションに追加されました( mltが提案したように)。%batchName%
異なるバッチを並行して実行する場合の影響を回避するために追加されました。ファイル名だけを抽出するfor
などの高度な文字列関数を利用できるようにするには、を使用する必要があることに注意してください。%%~nk
vbsGetPrivileges
最適化されたスクリプト構造、改善(ファイルのパスまたは名前を簡単に変更できるようになり、どこでも参照されるようになった変数を追加しました。.vbs
バッチを昇格する必要がある場合にのみファイルを削除します)
場合によっては、昇格に別の呼び出し構文が必要になりました。スクリプトが機能しない場合は、次のパラメータを確認してください。
set cmdInvoke=0
set winSysFolder=System32
最初のパラメータをに変更してset cmdInvoke=1
、問題がすでに解決されているかどうかを確認します。cmd.exe
昇格を実行するスクリプトに追加されます。
または、2番目のパラメーターをに変更してみてくださいwinSysFolder=Sysnative
。これは64ビットシステムで役立つ場合があります(ただし、ほとんどの場合は必須ではありません)。(ADBaileyはこれを報告しました)。「Sysnative」は、32ビットスクリプトホストから64ビットアプリケーションを起動する場合にのみ必要です(たとえば、Visual Studioビルドプロセス、または別の32ビットアプリケーションからのスクリプト呼び出し)。
パラメータがどのように解釈されるかをより明確にするために、今はのように表示していますP1=value1 P2=value2 ... P9=value9
。これは、パスなどのパラメータを二重引用符で囲む必要がある場合に特に便利です"C:\Program Files"
。
VBSスクリプトをデバッグする場合は、ここで//X
提案されているように、最初のパラメーターとしてパラメーターをWScript.exeに追加できます(CScript.exeで説明されていますが、WScript.exeでも機能します)。
@MiguelAngeloによって提供されるバグ修正:batchPathがcmdシェルで正しく返されるようになりました。この小さなスクリプトtest.cmd
は違いを示しています(cmd.exeで実行してから、Windowsエクスプローラーからダブルクリックして実行します)。
@echo off
setlocal
set a="%~0"
set b="%~dpnx0"
if %a% EQU %b% echo running shell execute
if not %a% EQU %b% echo running cmd shell
echo a="%~0", b="%~dpnx0"
pause
便利なリンク: