バッチ(.bat)は手動実行だと共有フォルダ(Z: など)へアクセスできるのに、タスクスケジューラ経由だと
「パスが見つかりません」「アクセスが拒否されました」と失敗することがあります。主因は UAC による
ドライブマップの分離(Split Token) で、ユーザーがログオン時に作ったドライブレターが昇格プロセスや
スケジューラからは見えないためです。本記事では原因の仕組みと、実務での解決策(推奨順)を示します。
原因:昇格トークンと非昇格トークンでドライブマップが別
UAC 有効環境ではユーザーに「非昇格」と「昇格」の二種類のトークンがあり、ネットワークドライブのマッピングはトークンごとに独立しています。
通常、Z: を作ったのは非昇格セッション。一方、タスクスケジューラ(最上位の特権)
や SYSTEM
実行は別トークンのため、
その Z: を認識できません。その結果、手動実行は成功、タスクは失敗という現象になります。
解決策1(最優先):UNC パスを直接使う
ドライブレター(Z:, X: 等)をやめ、UNC(\\server\share\path
)を直接指定します。これが最も安全で、UAC の分離の影響を受けません。
@echo off
cd /d "%~dp0"
copy "\\filesrv01\deploy\package.zip" "C:\apps\package.zip"
robocopy "\\filesrv01\log$" "C:\bk\log" /E
解決策2:タスク内でドライブを再マップする(資格情報を明示)
タスクの先頭で net use
により、タスク側のトークンで改めてマッピングします。必要なら資格情報を渡します。
@echo off
set "SHARE=\\filesrv01\share"
set "USER=DOMAIN\svc_batch"
set "PASS=SecretP@ss"
net use Z: /delete /y 2>nul
net use Z: "%SHARE%" /user:%USER% "%PASS%" /persistent:no || exit /b 1
rem 以降は Z: でアクセス可
xcopy Z:\input\*.csv C:\work\in\ /D /Y
パスワードを平文で置きたくない場合は cmdkey
で資格情報を事前登録し、net use
はユーザー名のみでマップします。
rem 事前登録(管理者プロンプト)
cmdkey /add:filesrv01 /user:DOMAIN\svc_batch /pass:SecretP@ss
rem タスク内
net use Z: "\\filesrv01\share" /user:DOMAIN\svc_batch /persistent:no
解決策3:EnableLinkedConnections でドライブを共有(再起動要)
UAC の仕様に対する回避策として、EnableLinkedConnections
を有効にすると、非昇格で作ったドライブマップを昇格トークン側にもリンクします。
組織ポリシーに沿って適用可否を判断し、再起動後に有効化されます。
@echo off
rem 管理者権限で実行
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" ^
/v EnableLinkedConnections /t REG_DWORD /d 1 /f
echo 設定しました。再起動後に有効になります。
PowerShell の例:
powershell -NoProfile -Command ^
"Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name EnableLinkedConnections -Type DWord -Value 1"
注意点として、ユーザーごとにマップしているドライブが昇格側へ見えるだけで、SYSTEM
実行には影響しません。
SYSTEM で共有にアクセスする場合は、共有側にコンピューターアカウント(DOMAIN\MACHINE$
)の権限を付与するか、後述のサービスアカウント実行に切り替えます。
解決策4:タスクの実行アカウントと権限の見直し
共有にアクセスできるサービスアカウントを作り、タスクはそのアカウントで実行します。
「最上位の特権で実行」をオンにし、必要な共有アクセス権(共有/NTFS)を付与します。SYSTEM 実行は共有に届かないことが多いので、ファイルサーバー側で機械アカウント権限を許容しない運用ではサービスアカウントが確実です。
schtasks /Create /TN "NightlyCopy" ^
/TR "cmd /c cd /d C:\Jobs ^& copyjob.bat 1>C:\Logs\copy.log 2>&1" ^
/SC DAILY /ST 02:00 /RL HIGHEST /RU "DOMAIN\svc_batch" /RP "SecretP@ss" /F
実用テンプレート(UNC+再マップ+待機ログ付き)
まずは UNC、それでも事情によりドライブレターが必要なら再マップ、という順で確実性を上げます。失敗時は即ログ化して調査を容易にします。
@echo off
setlocal EnableExtensions
cd /d "%~dp0"
set "SHARE=\\filesrv01\deploy"
set "DEST=C:\apps\deploy"
set "LOG=C:\Logs\deploy_%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%.log"
rem --- 1) まず UNC で試行 ---
robocopy "%SHARE%" "%DEST%" *.zip /XO /R:1 /W:1 /LOG+:"%LOG%" /TEE
if not errorlevel 8 goto :ok
rem --- 2) 必要なら再マップして再試行 ---
net use Z: /delete /y 2>nul
net use Z: "%SHARE%" /user:DOMAIN\svc_batch "SecretP@ss" /persistent:no || (
echo マップ失敗 >>"%LOG%" & exit /b 2
)
robocopy "Z:\" "%DEST%" *.zip /XO /R:1 /W:1 /LOG+:"%LOG%" /TEE
if errorlevel 8 (echo 失敗 >>"%LOG%" & exit /b 3)
:ok
echo 成功 >>"%LOG%"
endlocal & exit /b 0
チェックリスト(うまくいかないとき)
共有の権限(共有/NTFS)が実行アカウントに付いているか。タスクは「最上位の特権で実行」になっているか。ドライブレターではなく UNC を使っているか。必要ならタスク内で net use
しているか。EnableLinkedConnections
を入れた後に再起動したか。ログを残し(1>out 2>&1
)、エラーコードを確認しているか。
まとめ
タスクスケジューラで共有に届かない原因は、UAC によるトークン分離でドライブレターが見えなくなる点にあります。最も堅牢なのは UNC を使うこと。やむを得ずドライブレターが必要ならタスク側で再マップし、運用ポリシーが許すなら EnableLinkedConnections
を有効化します。実行アカウントは共有アクセス権を持つサービスアカウントに統一し、ログで即時に失敗点を特定できるようにしておくと、現場での安定運用につながります。