前回「Windows11上のHDD接続を監視するバッチファイルを作るための調査」で動作を確認したコマンドをバッチファイルにして、Windows11上で稼働させてみます。
バッチファイル
まずは実際に作成したバッチファイルです。
--------------------------------------------------------------
usb_watch.bat
--------------------------------------------------------------
@echo off
set TARGET_LABEL=USB-HDD
set DRIVE1=
set LOG=C:\temp\test\usb_watch\usb_watch.log
rem 今日の日付取得
set Today=%date:~0,4%-%date:~5,2%-%date:~8,2%
rem アラートメール送信用ファイルパス
set MailPs=C:\temp\test\usb_watch\mailbody.ps1
rem 外付けHDDのボリュームを取得
for /f "delims=" %%A in ('powershell -Command "(Get-Volume -FileSystemLabel '%TARGET_LABEL%').DriveLetter"') do set "DRIVE1=%%A:"
if not defined DRIVE1 (
echo [%Today% %time: =0%] 未接続 > %LOG%
goto ERROR
)
rem ドライブのアクセス確認
powershell -Command "try { Get-ChildItem '%DRIVE1%\' -ErrorAction Stop | Out-Null; exit 0 } catch { exit 1 }"
if errorlevel 1 (
echo [%Today% %time: =0%] アクセス不可 > %LOG%
goto ERROR
)
goto OK
:ERROR
rem ここに通知処理(メール・イベントログなど)
rem メールアラートの送信を実行
powershell -ExecutionPolicy Bypass -File "%MailPs%"
goto END
:OK
rem 正常時はログ出さない(何もせず終了)
goto END
:END
set TARGET_LABEL=
set DRIVE1=
set LOG=
set Today=
set MailPs=
--------------------------------------------------------------
環境の補足情報
解説の前に、環境の補足情報を。
USB接続の外付けHDDは、以下のようなディスクを想定したバッチファイルです。

このようにボリュームラベルが「USB-HDD」となっているHDDを対象にします。
また、ファイルの置き場は仮に<C:\temp\test\usb_watch>フォルダを想定しています。

(※実環境ではこれ以外の場所に置いています。)
バッチファイルの解説
変数「TARGET_LABEL」に代入したボリュームラベル(バッチファイル内で適宜書き換え)を
powershell -Command "(Get-Volume -FileSystemLabel '%TARGET_LABEL%').DriveLetter"
行のコマンドで存在確認をしています。
これをfor /fで囲んでいるのは、以前にもやった<バッチファイルのfor命令を学ぶサンプルバッチファイル - treedown’s Report>にあるように、コマンドの実行結果を変数%DRIVE1%に代入するための構文となります。
取得したドライブ情報の存在有無を確認してif not defined行で%DRIVE1%変数が空の場合にはログファイルに「未接続」のテキストを書き出すようにしています。
次の
powershell -Command "try { Get-ChildItem '%DRIVE1%\' -ErrorAction Stop | Out-Null; exit 0 } catch { exit 1 }"
では、ドライブが存在するけどRAW化などでアクセスできないケースを想定して、二重チェックをしています。
Get-Volumeでデバイスの有無確認はクリアしても、Get-ChildItemでファイルシステムの問題を確認することで、実際に(ドライブレターが存在していても)使えないという状態を検出する、という狙いです。
この判定は「if errorlevel 1」で実施しています。アクセスに失敗した場合には「アクセス不可」がログに記録されます。
上記二つのチェックでエラーが検出された場合には「ERROR」ラベルの処理として、メールアラートの送信を実行する「mailbody.ps1」を実行します。
※前回も記載しましたが、メールアラート「mailbody.ps1」のメール送信は、以前の<バッチファイルでWindowsサービス監視2023年版 - treedown’s Report>を流用しています。
エラーが発生していない場合には、「OK」ラベルの処理として何もせずに終了しています。
あと、ログファイルの記録は毎回「>」で上書きとして、蓄積しないようにしました。蓄積すると肥大化するログファイルを別途ローテーション処理する必要があるので蓄積しません。
タスクスケジューラで定期実行する
このバッチファイルをタスクスケジューラに仕掛けて定期実行します。

最上位の特権で実行するにチェックを入れてあります。
トリガは

スケジュールで1時間おきに定期実行をするようにしました。停止するまでの時間を30分にすることで、監視対象のHDDが応答しない時にもタスクスケジューラのジョブが(次回にジョブが起動するより前に)自動的に終了するように設定を入れました。

一時間おきの実行に加えて、OSの起動時にも実行するようにして、月一のWindows Update再起動後を想定したHDD認識不良が発生した時にもメールアラートが来るようにしました。
あと、設定タブで、

「要求時に実行中のタスクが終了しない場合、タスクを強制的に停止する」を有効化しておきました。またデフォルトですが"タスクが既に実行中の場合に適用される規則"には「新しいインスタンスを開始しない」であることを確認しています。
これで1回目が終わらずに2回目、3回目と応答しないデバイスのせいで処理が終わらない=プロセスが積みあがっていく、ということが発生しない対策としています。
動作テスト
テストはタスクスケジューラ上で実行してみることで、タスクスケジューラを経由してバッチファイルが正常動作するかの確認とします。

しかし、正常動作時には何もせず終了とするバッチファイルなので、ちゃんと動作しているのか、問題時には狙った通知をするのかが気になります。
今回はテストとして、

バッチファイルのボリュームラベルを「存在するボリュームラベル」を「存在しないボリュームラベル」に書き換えることで、ドライブが切断された状態を想定した動作確認を実施することにしました。
今後やってみたいこと
今回は、バッチファイルを見やすくすることと、あまり複雑にして未完成で頓挫することを避けるために、機能は絞り込んで短くシンプルに作成することにしました。
しかし、作成していてこんなことできるんじゃないか?と思えてきたのもあるので、必要に応じて、(そのうち)バッチファイルに機能を追加してみたいと思います。
思いついたのは、以下の項目でした。
- 故障したHDDは応答が非常に遅い(応答しない)ことがあるので、タイムアウトを設定して長時間応答しない場合には故障と判断(アラート送信)という処理ができないか
- 複数台USB接続の外付けHDDがあるPC環境では、複数台のHDDを監視したい。
- ログファイルを蓄積型にして、適当にローテーションできるようにしたほうがいいかも
機会があれば、上記もやってみようと思います。