【bat】バッチファイルで管理者権限を自動取得する方法

bat

バッチファイルで管理者権限(UACによる昇格)を自動取得する方法を丁寧に解説します。Windowsの操作を自動化するスクリプトは管理者権限が必要な処理(レジストリ変更、サービス操作、システム領域へのファイル書き込みなど)でよく使われますが、普通にバッチを実行すると権限不足で失敗することがあります。ここでは「自スクリプトが管理者でない場合に自身を昇格して再実行する」パターンを示し、その仕組み、実装例、注意点までまとめます。

仕組みの理解

UAC(User Account Control)はユーザー操作で昇格を要求する仕組みです。単に runas コマンドを使うだけでは UAC の昇格プロンプトを発生させられない場面があるため、PowerShell の Start-Process -Verb RunAs を使って新しいプロセスを「管理者として起動」し、自分自身(バッチファイル)を管理者権限で再実行するのが一般的です。まず「現在の実行が管理者かどうか」を判定し、管理者でなければ昇格用コマンドで再起動、管理者であれば本処理を続行する流れになります。

管理者判定の方法

管理者かどうかを判定する簡単な手法として net session コマンドを利用する方法があります。管理者権限がない場合 net session はエラーを返すため、その戻り値で判定できます。別の方法として whoami /groups で Administrators グループの存在を確認する手段もありますが、ここでは互換性が高くシンプルな net session を使ったサンプルを示します。

バッチの自己昇格(実用例)

以下は典型的な「自己昇格」パターンのバッチファイルです。管理者でなければ PowerShell で管理者として同じバッチを再実行します。スクリプト内で引数を受け渡すための工夫も含めています。

@echo off
setlocal

:: ---- 管理者判定(net session) ----
net session >nul 2>&1
if %errorlevel% == 0 (
    goto :Elevated
) else (
    goto :NotElevated
)

:NotElevated
:: 自分のフルパスを取得(スペースを含むパス対応)
set "this=%~f0"
:: 引数をそのまま再渡し
set "args=%*"
:: PowerShellを使って管理者として再実行
powershell -Command "Start-Process -FilePath 'cmd.exe' -ArgumentList '/c \"%this%\" %args%' -Verb RunAs"
:: Start-Processが呼ばれたあとは現在のプロセスを終了
exit /b

:Elevated
:: ここから管理者権限で動作する処理を記述
echo 管理者権限で実行されています。
:: 例:システムフォルダへファイルコピー(動作確認用)
echo テストファイルを書き込みます...
copy "%~dp0sample.txt" "%windir%\Temp\" >nul 2>&1
if %errorlevel% == 0 (
    echo 書き込み成功
) else (
    echo 書き込み失敗(パスやファイルを確認してください)
)

endlocal
pause

ポイント解説

このサンプルでは net session による簡易判定を行い、管理者でないと PowerShell の Start-Process -Verb RunAs を使って cmd.exe を管理者権限で起動しています。Start-Process の -ArgumentList で渡す引数は、cmd /c 内でバッチファイルを呼び出す形にしているため、引数もそのまま引き継げます。注意点としてはパスにスペースが含まれる場合のクォート処理、そしてユーザーが UAC の昇格プロンプトで拒否した場合は再実行されない点があります。

代替の判定と昇格方法

net session が使えない環境やより堅牢に判定したい場合は PowerShell を使って判定する方法もあります。PowerShell での判定は [System.Security.Principal.WindowsIdentity] と [System.Security.Principal.WindowsPrincipal] を使って Administrators グループに属しているかをチェックします。バッチから PowerShell 判定を呼び出すパターンを使えば環境差を吸収できます。

PowerShell判定+自己昇格の例

より確実に判定して昇格する例を示します。PowerShell のワンライナーで判定し、昇格が必要なら Start-Process で再起動します。

@echo off
setlocal

:: PowerShellで管理者判定
powershell -Command ^
    "if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { exit 1 } else { exit 0 }"
if %errorlevel% == 0 (
    goto :Elevated
) else (
    goto :NotElevated
)

:NotElevated
set "this=%~f0"
set "args=%*"
powershell -Command "Start-Process -FilePath 'powershell' -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%this%"" %args%' -Verb RunAs"
exit /b

:Elevated
echo 管理者権限で処理を行います...
rem ここに管理者で行う処理を記述
endlocal
pause

注意点とセキュリティ考慮

UAC 昇格はユーザーに対して明示的な同意を求めるべき操作です。自動で無理に昇格させることはできないため、ユーザーがプロンプトを拒否した場合のフォールバック処理を用意することが重要です。管理者権限で実行する処理は最小限にとどめ、可能なら管理者でない状態でも動作するように処理を分離する設計が望ましいです。また、バッチ内に平文で秘密情報やパスワードを置かない、外部からの入力を検証するなど基本的なセキュリティ対策を忘れないでください。

トラブルシューティング

UACプロンプトが出ない、あるいは Start-Process が失敗する場合はPowerShellのポリシーや環境依存が原因のことがあります。企業ポリシーで昇格が制限されている場合は、管理者に相談してタスクスケジューラを使った昇格(管理者権限でのタスク登録)や、管理者が署名した実行ファイルを配布する方法を検討してください。リモート環境やサービスアカウントでの自動実行には別のアプローチが必要です。

まとめ

バッチファイルでの管理者自動取得は「現在の実行が管理者か判定 → 管理者でなければ PowerShell の Start-Process -Verb RunAs で自身を管理者として再起動 → 管理者なら本処理を実行」というパターンが基本です。net session を使った簡易判定か、PowerShell を使った堅牢な判定かを選び、UAC の拒否やポリシー制約に備えたフォールバックを用意することが実運用でのポイントとなります。