【bat】共有フォルダへの接続エラーを自動検出・リカバリする方法|net use・リトライ処理・ログ出力まで完全解説

【bat】共有フォルダへの接続エラーを自動検出・リカバリする方法|net use・リトライ処理・ログ出力まで完全解説 bat

業務でバッチファイルを使ってネットワーク共有フォルダにアクセスする場合、突然の接続断やネットワーク障害によってスクリプトが途中で止まることがあります。手動で対応していては業務効率が落ちるだけでなく、夜間バッチや定期処理では誰も気づかないまま処理が止まるリスクもあります。

本記事では、バッチファイルで共有フォルダへの接続状態を事前に確認し、エラーを検出した場合に自動で再接続を試みるリカバリ処理の実装方法を解説します。基本構文から、リトライロジック・ログ出力・セキュリティ対策まで順を追って紹介します。

この記事で学べること

  • 共有フォルダへの接続確認方法(if exist / net use
  • 接続失敗時の自動再接続(リトライ処理)
  • ping による事前のサーバー死活確認
  • 接続ログの自動記録
  • パスワードを直書きしないセキュリティ対策(cmdkey
  • タスクスケジューラとの連携時の注意点
スポンサーリンク

共有フォルダへの接続確認の基本

まず最も基本的な方法として、if exist を使って共有フォルダにアクセスできるかを確認します。UNCパス(\\サーバー名\共有名)を直接チェックする方法と、ネットワークドライブ(Z: など)をチェックする方法があります。

UNCパスで直接確認
@echo off
setlocal

set "SHARE=\\192.168.1.100\shared"

if exist "%SHARE%\" (
    echo [OK] 共有フォルダに接続できます。
) else (
    echo [ERROR] 共有フォルダに接続できません。
)

endlocal

ドライブレターが割り当てられている場合は以下のようにチェックします。

ネットワークドライブで確認
@echo off
setlocal

set "DRIVE=Z:"

if exist "%DRIVE%\" (
    echo [OK] %DRIVE% は接続済みです。
) else (
    echo [ERROR] %DRIVE% は未接続です。
)

endlocal

注意:if exist の落とし穴

Windowsは一度接続に成功したパスをキャッシュすることがあります。特にタスクスケジューラ経由ではキャッシュが効かず、実際にアクセスできない場合でも if exist が通ってしまうケースがあります。確実に確認したい場合はファイルの読み書きや net use コマンドのステータス確認を併用してください。

接続エラー検出と自動再接続(基本版)

接続が切れていた場合に net use で再接続を試みる基本スクリプトです。再接続前に既存の接続を削除してからマウントし直すことで、古い接続情報が残って失敗するトラブルを防ぎます。

接続確認+自動再接続(基本版)
@echo off
setlocal

set "SHARE=\\192.168.1.100\shared"
set "DRIVE=Z:"
set "USER=DOMAIN\username"
set "PASS=password"
set "LOG=%~dp0connect_log.txt"

echo ==== 処理開始 %DATE% %TIME% ==== >> "%LOG%"

:: ドライブが接続済みか確認
if exist "%DRIVE%\" (
    echo [INFO] %DRIVE% は接続済みです。 >> "%LOG%"
    goto :MAIN
)

:: 未接続の場合は再接続を試みる
echo [WARN] %DRIVE% が未接続。再接続を試みます。 >> "%LOG%"

:: 既存の接続を削除(残骸を防ぐ)
net use %DRIVE% /delete /yes >nul 2>&1

:: 再接続実行
net use %DRIVE% "%SHARE%" /user:%USER% %PASS% >> "%LOG%" 2>&1

:: 再接続確認
if exist "%DRIVE%\" (
    echo [INFO] 再接続に成功しました。 >> "%LOG%"
    goto :MAIN
)

echo [ERROR] 再接続に失敗しました。処理を中断します。 >> "%LOG%"
echo ==== 処理終了(エラー) %DATE% %TIME% ==== >> "%LOG%"
exit /b 1

:MAIN
:: ここに本来の処理を記述
echo [INFO] 共有フォルダへのアクセスを確認しました。 >> "%LOG%"
copy "%DRIVE%\data.txt" "%~dp0backup\" >> "%LOG%" 2>&1

echo ==== 処理終了 %DATE% %TIME% ==== >> "%LOG%"
endlocal

ポイント

  • %~dp0 でスクリプトと同じフォルダにログを出力するのがおすすめです
  • net use /delete を先に実行することで古い接続情報をリセットできます
  • goto :MAIN で共通処理部分へジャンプし、コードの重複を避けます

リトライ処理を組み込む(実務向け)

一時的なネットワーク瞬断では、少し待ってから再試行すれば復旧することがよくあります。ループを使って複数回リトライする処理を組み込むと、より堅牢なスクリプトになります。

リトライロジック付き接続確認
@echo off
setlocal enabledelayedexpansion

set "SHARE=\\192.168.1.100\shared"
set "DRIVE=Z:"
set "USER=DOMAIN\username"
set "PASS=password"
set "LOG=%~dp0connect_log.txt"
set "RETRY_MAX=3"
set "RETRY_WAIT=5"

echo ==== 処理開始 %DATE% %TIME% ==== >> "%LOG%"

:: 接続確認ループ
set "CONNECTED=0"
for /L %%i in (1,1,%RETRY_MAX%) do (
    if !CONNECTED! == 0 (
        if exist "%DRIVE%\" (
            echo [INFO] [試行%%i] %DRIVE% に接続済みです。 >> "%LOG%"
            set "CONNECTED=1"
        ) else (
            echo [WARN] [試行%%i] %DRIVE% が未接続。再接続を試みます。 >> "%LOG%"
            net use %DRIVE% /delete /yes >nul 2>&1
            net use %DRIVE% "%SHARE%" /user:%USER% %PASS% >nul 2>&1
            if exist "%DRIVE%\" (
                echo [INFO] [試行%%i] 再接続に成功しました。 >> "%LOG%"
                set "CONNECTED=1"
            ) else (
                echo [WARN] [試行%%i] 接続失敗。%RETRY_WAIT%秒後にリトライします。 >> "%LOG%"
                timeout /t %RETRY_WAIT% /nobreak >nul
            )
        )
    )
)

:: 最終判定
if !CONNECTED! == 0 (
    echo [ERROR] %RETRY_MAX%回試みましたが接続できませんでした。処理を中断します。 >> "%LOG%"
    echo ==== 処理終了(エラー) %DATE% %TIME% ==== >> "%LOG%"
    exit /b 1
)

:: 本来の処理
echo [INFO] メイン処理を開始します。 >> "%LOG%"
copy "%DRIVE%\data.txt" "%~dp0backup\" >> "%LOG%" 2>&1

echo ==== 処理終了 %DATE% %TIME% ==== >> "%LOG%"
endlocal

このスクリプトでは setlocal enabledelayedexpansion!CONNECTED! を使っています。FOR ループ内でフラグ変数を参照するには遅延展開が必要です。詳しくはsetlocal enabledelayedexpansionの使い方と遅延展開の仕組みを参照してください。

ping でサーバー死活確認を行ってから接続する

ネットワークドライブのマウントを試みる前に、ping でサーバー自体が応答するかを確認しておくと、接続タイムアウトで長時間待たされるのを防げます。

ping で死活確認してから接続
@echo off
setlocal

set "SERVER=192.168.1.100"
set "SHARE=\\%SERVER%\shared"
set "DRIVE=Z:"
set "LOG=%~dp0connect_log.txt"

echo ==== 処理開始 %DATE% %TIME% ==== >> "%LOG%"

:: サーバーへの ping 確認(1回のみ、タイムアウト1秒)
ping -n 1 -w 1000 %SERVER% >nul 2>&1
if errorlevel 1 (
    echo [ERROR] サーバー %SERVER% に到達できません。ネットワーク障害の可能性があります。 >> "%LOG%"
    echo ==== 処理終了(エラー) %DATE% %TIME% ==== >> "%LOG%"
    exit /b 1
)

echo [INFO] サーバー %SERVER% への疎通を確認しました。 >> "%LOG%"

:: ドライブ接続確認
if not exist "%DRIVE%\" (
    net use %DRIVE% /delete /yes >nul 2>&1
    net use %DRIVE% "%SHARE%" >nul 2>&1
    if not exist "%DRIVE%\" (
        echo [ERROR] ドライブマウントに失敗しました。 >> "%LOG%"
        exit /b 1
    )
)

echo [INFO] 接続確認完了。メイン処理を開始します。 >> "%LOG%"
endlocal

注意:ping が通っても共有フォルダにアクセスできない場合があります

ping はICMPプロトコルを使うため、ファイル共有(SMBポート445)とは独立しています。pingが通っても共有フォルダの権限エラーやSMBの問題でアクセスできない場合があります。ping はあくまで「サーバーが生きているか」の簡易確認として使いましょう。

net use の戻り値でエラー内容を判別する

net use コマンドは ERRORLEVEL に戻り値をセットします。0 は成功、それ以外はエラーです。エラーコードによって原因を特定できます。

ERRORLEVEL 主な原因 対処法
0 成功
2 ファイルが見つからない(パスが間違い) 共有名・パスを確認
5 アクセス拒否(権限不足) ユーザー・パスワードを確認
53 サーバーが見つからない(ネットワーク到達不能) pingで疎通確認
67 ネットワーク名が見つからない 共有名・サービス状態を確認
86 ネットワークパスワードが間違っている 認証情報を確認
1219 同じサーバーに複数の資格情報で接続しようとしている net use /delete で既存削除
ERRORLEVEL で原因を判別する
@echo off
setlocal

set "DRIVE=Z:"
set "SHARE=\\192.168.1.100\shared"

net use %DRIVE% "%SHARE%" >nul 2>&1
set "ERR=%errorlevel%"

if %ERR% == 0 (
    echo 接続成功
    goto :END
)

if %ERR% == 53   echo [ERROR 53] サーバーに到達できません(ネットワーク障害)
if %ERR% == 5    echo [ERROR 5] アクセスが拒否されました(権限エラー)
if %ERR% == 86   echo [ERROR 86] パスワードが間違っています
if %ERR% == 1219 echo [ERROR 1219] 同一サーバーへの複数接続が競合しています

:END
endlocal

ポイント:errorlevel を変数に保存する

net use の後すぐに別のコマンドを実行すると、そのコマンドによって ERRORLEVEL が上書きされます。set "ERR=%errorlevel%" で即座に変数に保存しておくのが安全です。詳しくはエラー時に処理を中断・終了する方法を参照してください。

パスワードをスクリプトに直書きしない(セキュリティ対策)

前述のサンプルでは説明のためにパスワードを直書きしていましたが、実務では絶対に避けてください。スクリプトファイルを誰かが閲覧・共有すると認証情報が漏洩します。主な対策方法を2つ紹介します。

方法1:cmdkey で資格情報を事前登録する

Windowsの「資格情報マネージャー」に接続情報を登録しておくと、スクリプト内でパスワードを指定しなくても自動認証されます。

資格情報の事前登録(コマンドプロンプトで一度だけ実行)
cmdkey /add:192.168.1.100 /user:DOMAIN\username /pass:password

登録後は以下のように書けます。パスワードの記述が不要になります。

パスワード不要の接続(cmdkey登録済みの場合)
@echo off
setlocal

set "DRIVE=Z:"
set "SHARE=\\192.168.1.100\shared"

:: パスワード指定不要(資格情報マネージャーが自動補完)
net use %DRIVE% "%SHARE%"

endlocal

方法2:外部ファイルから読み込む

パスワードを別ファイルに分離して、本番環境のみアクセス制限をかける方法もあります。ただし、ファイル自体の保護(アクセス権・暗号化)が前提です。

credentials.txt
DOMAIN\username
password
外部ファイルから認証情報を読み込む
@echo off
setlocal enabledelayedexpansion

set "CRED_FILE=%~dp0credentials.txt"
set "DRIVE=Z:"
set "SHARE=\\192.168.1.100\shared"

:: 1行目=ユーザー名, 2行目=パスワード
set "LINE=0"
for /f "usebackq delims=" %%A in ("%CRED_FILE%") do (
    set /a LINE+=1
    if !LINE! == 1 set "USER=%%A"
    if !LINE! == 2 set "PASS=%%A"
)

net use %DRIVE% "%SHARE%" /user:!USER! !PASS!
endlocal

完全版:リトライ+ログ+エラー通知スクリプト

実務で使える完全版スクリプトです。リトライ・ログ出力・エラー時のWindowsイベントログ書き込みを組み合わせています。

recover_share.bat(完全版)
@echo off
setlocal enabledelayedexpansion

:: ===== 設定 =====
set "SERVER=192.168.1.100"
set "SHARE=\\%SERVER%\shared"
set "DRIVE=Z:"
set "USER=DOMAIN\username"
set "PASS=password"
:: ※ パスワード直書きを避けたい場合は cmdkey で事前登録し、/user/%PASS% を削除すること
set "LOG=%~dp0recover_log.txt"
set "RETRY_MAX=3"
set "RETRY_WAIT=10"

:: ===== 開始ログ =====
echo ==== 処理開始 %DATE% %TIME% ==== >> "%LOG%"

:: ===== サーバー疎通確認 =====
ping -n 1 -w 2000 %SERVER% >nul 2>&1
if errorlevel 1 (
    echo [ERROR] サーバー %SERVER% への疎通失敗。 >> "%LOG%"
    goto :ERROR
)
echo [INFO] サーバー疎通OK。 >> "%LOG%"

:: ===== リトライ付き接続確認 =====
set "CONNECTED=0"
for /L %%i in (1,1,%RETRY_MAX%) do (
    if !CONNECTED! == 0 (
        if exist "%DRIVE%\" (
            set "CONNECTED=1"
            echo [INFO] [試行%%i] %DRIVE% 接続済み。 >> "%LOG%"
        ) else (
            net use %DRIVE% /delete /yes >nul 2>&1
            net use %DRIVE% "%SHARE%" /user:%USER% %PASS% >nul 2>&1
            if exist "%DRIVE%\" (
                set "CONNECTED=1"
                echo [INFO] [試行%%i] 再接続成功。 >> "%LOG%"
            ) else (
                echo [WARN] [試行%%i] 接続失敗。%RETRY_WAIT%秒待機。 >> "%LOG%"
                timeout /t %RETRY_WAIT% /nobreak >nul
            )
        )
    )
)

if !CONNECTED! == 0 goto :ERROR

:: ===== メイン処理 =====
echo [INFO] メイン処理開始。 >> "%LOG%"

xcopy "%DRIVE%\data" "%~dp0backup\" /e /i /y >> "%LOG%" 2>&1
if errorlevel 1 (
    echo [ERROR] xcopy に失敗しました。 >> "%LOG%"
    goto :ERROR
)

echo [INFO] メイン処理完了。 >> "%LOG%"
echo ==== 処理終了 %DATE% %TIME% ==== >> "%LOG%"
exit /b 0

:: ===== エラー終了 =====
:ERROR
echo [ERROR] エラーにより処理を中断しました。 >> "%LOG%"
echo ==== 処理終了(エラー) %DATE% %TIME% ==== >> "%LOG%"
:: Windowsイベントログに書き込み(管理者権限が必要)
eventcreate /t ERROR /id 100 /l APPLICATION /d "recover_share.bat: 共有フォルダ接続失敗" >nul 2>&1
exit /b 1

eventcreate コマンドについて

eventcreate はWindowsイベントログにカスタムメッセージを書き込むコマンドです。管理者権限が必要ですが、タスクスケジューラと組み合わせると、エラー発生時にイベントビューアーで検知・監視ができます。エラーログのファイル出力と組み合わせてより詳細に残したい場合はバッチファイルでエラーログを自動収集して保存する方法も参照してください。

タスクスケジューラで動かす場合の注意点

タスクスケジューラからバッチを実行する場合、ユーザーがログオンしていなくても動作しますが、その際はネットワークドライブ(Z: など)が使えないことがあります。これはWindowsのセキュリティ仕様(UAC・セッション分離)によるものです。

詳細はタスクスケジューラでネットワーク共有にアクセスできないときの解決策(EnableLinkedConnections)をご参照ください。

タスクスケジューラでの動作を前提とする場合は、ドライブレターではなくUNCパスを直接使う方法が最も確実です。

タスクスケジューラ向け:UNCパスを直接使う
@echo off
setlocal

:: ドライブレターではなくUNCパスを直接使う
set "SHARE=\\192.168.1.100\shared"

if exist "%SHARE%\" (
    echo [OK] 接続確認済み。
    xcopy "%SHARE%\data" "C:\backup\" /e /i /y
) else (
    echo [ERROR] 共有フォルダにアクセスできません。
    exit /b 1
)

endlocal

関連記事:共有フォルダ・ネットワークドライブの基礎

本記事ではエラー検出とリカバリに特化しましたが、net use の基本構文やUNCパスの使い方はバッチファイルで共有フォルダにアクセスする方法で詳しく解説しています。

また、ネットワークドライブの永続マウントや起動時の自動マウントスクリプト全般についてはnet useでネットワークドライブを自動マウントする方法も参考にしてください。

よくある質問(FAQ)

共有フォルダが見えているのに if exist が失敗することがある
ネットワークドライブはWindowsキャッシュの影響で、一見接続されているように見えても実際にはアクセスできない「ゴースト状態」になることがあります。if exist の代わりに dir "%DRIVE%\*" を実行してエラーレベルで判定するか、実際にファイルの読み書きを試みる方法も有効です。
net use が突然エラーになる原因は?
主な原因は(1)ネットワーク接続の瞬断、(2)サーバー側でのセッションタイムアウト、(3)ドメイン認証の期限切れ、(4)同一サーバーへの複数資格情報による競合(ERRORLEVEL 1219)が挙げられます。特に夜間バッチでは(2)が起きやすいため、処理開始時に毎回 net use /delete してから再接続するのが安定します。
タスクスケジューラから実行するとネットワークドライブにアクセスできない
タスクスケジューラは別セッションで動作するため、ユーザーがマップしたドライブレター(Z: など)が見えません。UNCパスを直接使うか、EnableLinkedConnections レジストリを設定する方法があります。詳しくはタスクスケジューラでネットワーク共有にアクセスできないときの解決策をご参照ください。
パスワードなしで接続する方法はあるか?
cmdkey コマンドでWindowsの資格情報マネージャーに登録しておくと、スクリプト内でパスワードを書かずに接続できます。また、Active Directoryドメイン環境ではドメイン認証が自動的に使われるため、パスワードの指定自体が不要なケースも多いです。
リトライ回数や待機時間はどのくらいが適切か?
一般的には3〜5回のリトライ、待機時間は5〜30秒が目安です。ネットワーク環境や業務の許容待機時間に合わせて調整してください。過度なリトライは他プロセスへの影響もあるため、最大でも5回程度に抑えるのが無難です。

まとめ

バッチファイルでの共有フォルダ接続エラー検出と自動リカバリのポイントをまとめます。

  • 接続確認if exist "%DRIVE%" または UNCパスで確認
  • 自動再接続net use /deletenet use の順で実行
  • リトライ処理for /L ループ+フラグ変数で複数回試行
  • 事前確認ping でサーバー疎通チェックをしてから接続
  • セキュリティ:パスワードは cmdkey で資格情報マネージャーに登録
  • タスクスケジューラ対応:ドライブレターではなくUNCパスを使う

ネットワーク障害に強い自動回復付きバッチスクリプトを構築することで、業務処理の安定稼働と運用負担の軽減が実現できます。共有フォルダへのアクセス基礎についてはバッチファイルで共有フォルダにアクセスする方法もあわせてご確認ください。