バッチ(.bat)で Program Files
配下への書き込み、サービス操作、ドライバや HKLM レジストリ変更などを行うと UAC により
「管理者として実行」が必須になります。権限不足のまま動かすと「アクセスが拒否されました」「要求された操作には管理者特権が必要です」などで失敗します。
ここでは「管理者かどうかの判定」「自己昇格(再起動)」「無人実行(タスクスケジューラ)」「よくある落とし穴(ネットワークドライブ・SysWOW64・SmartScreen)」まで、実務向けにまとめます。
1. まず“管理者として実行”になっているか判定する
非昇格だと失敗する処理に入る前に判定します。net session
や whoami /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 を明示。
これらをテンプレート化しておけば、管理者権限が絡むバッチの失敗を大幅に減らし、現場での再現・調査も容易になります。