【bat】管理者権限が必要な処理が失敗するときの解決策

バッチ(.bat)で Program Files 配下への書き込み、サービス操作、ドライバや HKLM レジストリ変更などを行うと UAC により
「管理者として実行」が必須になります。権限不足のまま動かすと「アクセスが拒否されました」「要求された操作には管理者特権が必要です」などで失敗します。
ここでは「管理者かどうかの判定」「自己昇格(再起動)」「無人実行(タスクスケジューラ)」「よくある落とし穴(ネットワークドライブ・SysWOW64・SmartScreen)」まで、実務向けにまとめます。

1. まず“管理者として実行”になっているか判定する

非昇格だと失敗する処理に入る前に判定します。net sessionwhoami /groups が簡単です。

@echo off
rem --- 権限チェック(どちらかでOK) ---
net session >nul 2>&1
if errorlevel 1 goto elevate

whoami /groups | find "S-1-5-32-544" >nul
if errorlevel 1 goto elevate

echo 管理者権限を確認しました。
goto :main

:elevate
echo この処理には管理者権限が必要です。昇格して再実行します…

2. 自己昇格:同じバッチを“管理者として再実行”する

PowerShell の Start-Process -Verb RunAs を使うのが手軽です(UAC プロンプト表示)。

powershell -NoProfile -Command ^
  "Start-Process -FilePath '%~f0' -ArgumentList '%*' -WorkingDirectory '%CD%' -Verb RunAs"
exit /b

PowerShell が使えない環境向けに、WSH(VBScript)で昇格する方法もあります。

rem --- 代替(VBScript) ---
>"%temp%\elev.vbs" echo Set sh=CreateObject("Shell.Application")
>>"%temp%\elev.vbs" echo sh.ShellExecute "%~f0", "%*", "%CD%", "runas", 1
cscript //nologo "%temp%\elev.vbs"
del "%temp%\elev.vbs"
exit /b

3. 無人運用:タスクスケジューラで“最上位の特権で実行”

夜間バッチなど人手なしで昇格実行する場合はスケジューラ登録が確実です。

schtasks /Create /TN "MyAdminJob" ^
  /TR "cmd /c C:\Scripts\job.bat args" ^
  /SC DAILY /ST 02:00 ^
  /RL HIGHEST /F

GUI では「最上位の特権で実行」「ログオンしているかどうかにかかわらず実行」を有効化し、実行アカウントは権限を持つユーザーに設定します。

4. “権限を要しない設計”への置き換えも検討

  • 保存先の見直し: %ProgramFiles% ではなく %ProgramData%、ユーザー設定は %LocalAppData% / %AppData%
  • レジストリ: 可能なら HKLM ではなく HKCU 配下へ。
  • サービス操作: 設定反映と再起動を分離し、再起動だけ昇格タスクに委任。

5. “権限があるのに失敗”の落とし穴と対処

5.1 昇格後にネットワークドライブが見えない

UAC により非昇格と昇格でトークンが分かれ、マップドドライブは共有されません。UNC でアクセスするか、昇格環境で再マップします。

rem UNC 利用(推奨)
copy "\\server\share\in.txt" "C:\work\in.txt"
rem または昇格側で再マップ
net use Z: "\\server\share" /user:DOMAIN\User P@ss

ポリシーで共有したい場合はレジストリ HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLinkedConnections=1 を検討(再起動要)。組織のセキュリティ方針に従ってください。

5.2 32bit/64bit のファイルシステムリダイレクト

32bit プロセス経由で %SystemRoot%\System32 にアクセスすると SysWOW64 にリダイレクトされます。64bit 実体へは %SystemRoot%\Sysnative を使用。

"%SystemRoot%\Sysnative\sc.exe" query type= service

5.3 SmartScreen/Zone.Identifier によるブロック

ダウンロード直後の .bat/.exe がブロック属性で実行制限されることがあります。解除してから実行します。

powershell -NoProfile -Command "Unblock-File -Path 'C:\Scripts\job.bat'"

5.4 Program Files 直下の書き込み

管理者でもロック中は失敗します。関連サービス/アプリを停止してから実施し、恒常的な書き込みは %ProgramData% へ移す設計に。

5.5 レジストリの 32/64bit ハイブ違い

HKLM\Software は 32bit から見ると WOW6432Node 側になります。必要に応じて /reg:64 / /reg:32 を使い分けます。

reg add "HKLM\Software\MyApp" /v Installed /t REG_DWORD /d 1 /f /reg:64

6. 昇格前提のテンプレート(そのまま使える雛形)

@echo off
setlocal EnableExtensions
rem --- 管理者判定。NGなら自己昇格 ---
net session >nul 2>&1 || (
  powershell -NoProfile -Command ^
    "Start-Process -FilePath '%~f0' -ArgumentList '%*' -WorkingDirectory '%CD%' -Verb RunAs"
  exit /b
)

rem --- メイン処理例 ---
echo [1/3] サービス停止…
"%SystemRoot%\Sysnative\sc.exe" stop MyService >nul 2>&1

echo [2/3] 設定配置…
if not exist "%ProgramData%\MyApp" mkdir "%ProgramData%\MyApp"
copy /y "%~dp0config.xml" "%ProgramData%\MyApp\config.xml" >nul || (echo 配置失敗 & exit /b 1)

echo [3/3] レジストリ更新…
reg add "HKLM\Software\MyApp" /v Updated /t REG_SZ /d "%DATE% %TIME%" /f >nul

echo サービス起動…
"%SystemRoot%\Sysnative\sc.exe" start MyService >nul 2>&1
echo 完了
exit /b 0

7. まとめ:失敗を減らすチェックリスト

  • 開始時に 権限チェック → 不足なら 自己昇格
  • 無人運用は タスクスケジューラ(最上位の特権) を利用。
  • 書き込み先は %ProgramData% / %LocalAppData% へ寄せ、HKCU 活用を検討。
  • 昇格後は UNC パス(または再マップ)、必要なら Sysnative 経由。
  • ダウンロード物は Unblock-File、レジストリは /reg:64 / /reg:32 を明示。

これらをテンプレート化しておけば、管理者権限が絡むバッチの失敗を大幅に減らし、現場での再現・調査も容易になります。