【実務・中級編】【初心者向け】Drive.IsReadyプロパティを活用した未挿入ドライブや光学メディアへのアクセスエラー防止 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

「動けばいい」という甘えを捨てろ:VBScriptにおけるドライブアクセス制御の極意

業務自動化の世界において、エンジニアの価値は「正常系」のコードを書くことではなく、「異常系」をいかにエレガントに、かつ堅牢に制御できるかで決まる。

多くの初学者が陥る罠がある。それは、USBメモリや外付けHDD、あるいはCD/DVDドライブといった「物理的な状態に左右されるデバイス」を扱う際、あたかもそれらが常にそこに存在し、常に即座に応答することを前提にコードを書いてしまうことだ。

結果として待っているのは、ユーザーがメディアを抜き取った瞬間に発生する、無慈悲な「デバイスの準備ができていません(Device not ready)」というランタイムエラー。そして、それによって停止する業務プロセス。

本稿では、`FileSystemObject` (FSO) の `Drive.IsReady` プロパティを軸に、プロフェッショナルが実践する「エラーを未然に防ぐための設計思想」を伝授する。

1. なぜ `On Error Resume Next` だけでは不十分なのか

初心者はエラーに直面すると、即座に `On Error Resume Next` を書き込む。確かに、スクリプトの停止は防げる。しかし、それは「問題を解決した」のではなく、「問題を隠蔽した」だけだ。

エラーを隠蔽したコードは、以下の致命的なリスクを孕む。

1. デバッグの困難化: どこで、なぜ失敗したのかがログに残らず、原因究明に膨大な時間を費やすことになる。
2. データの整合性破壊: ドライブへの書き込みに失敗したにもかかわらず、処理が続行され、後続のデータベース更新やファイル連携が「成功した」と誤認される。
3. リソースのリーク: エラー発生時にオブジェクトの解放処理が適切に行われず、メモリやハンドルを掴みっぱなしにする可能性がある。

真のプロフェッショナルは、エラーが発生してから対処するのではなく、「エラーが発生し得ない状態」を事前に確認する「防御的プログラミング(Defensive Programming)」を選択する。そのためのゲートキーパーこそが、`Drive.IsReady` である。

2. `Drive.IsReady` による状態判定のメカニズム

`FileSystemObject` を介して取得できる `Drive` オブジェクトには、そのドライブが現在、ファイルシステムへのアクセスを許可できる状態にあるかを示す `IsReady` プロパティが存在する。

このプロパティの真価は、「物理的な存在確認」と「論理的な準備完了確認」を同時に、かつ極めて軽量に行える点にある。

  • USBメモリが挿入されていない場合: `False` を返す。
  • CD/DVDドライブにメディアが入っていない場合: `False` を返す。
  • メディアは存在するが、ファイルシステムが壊れている、あるいは読み取り不能な場合: `False` を返す。

この判定を、ファイル操作(`Folder.Open` や `File.Open`)の直前に挟む。これが設計の鉄則だ。

3. プロダクションレベルの実装パターン

以下に、実務でそのまま利用可能な、堅牢な設計思想に基づいたコード例を示す。単なる判定だけでなく、ドライブのタイプ(リムーバブルか、光学メディアか)を特定し、目的に合致したデバイスのみを対象とする設計にしている。

'**
' Script Name: RobustDriveAccess.vbs
' Description: IsReadyプロパティを用いた、安全なドライブ操作のテンプレート
' Author: Chief Architect
'**

Option Explicit

Dim fso, targetDriveLetter, drive

' --- 設定エリア ---
targetDriveLetter = "E:"  ' 対象とするドライブレターを指定
' ------------------

Set fso = CreateObject("Scripting.FileSystemObject")

' メイン処理の実行
Call Main(fso, targetDriveLetter)

' オブジェクトの解放(ライフサイクル管理)
Set fso = Nothing

Sub Main(objFSO, strDriveLetter)
    On Error Resume Next ' 致命的なエラー以外は、個別にハンドリングする設計にする
    
    ' 1. ドライブオブジェクトの取得
    If Not objFSO.DriveExists(strDriveLetter) Then
        MsgBox "エラー: ドライブ " & strDriveLetter & " がシステムに認識されていません。", vbCritical, "致命的エラー"
        Exit Sub
    End If
    
    Set drive = objFSO.Drives(strDriveLetter)
    
    ' 2. 【極めて重要】IsReadyによる事前判定
    ' ここで判定を行うことで、後続のファイル操作でのランタイムエラーを完全に回避する
    If Not drive.IsReady Then
        MsgBox "警告: ドライブ " & strDriveLetter & " は準備ができていません。" & vbCrLf & _
               "メディアが挿入されているか確認してください。", vbExclamation, "デバイス未準備"
        Exit Sub
    End If
    
    ' 3. デバイスタイプの検証(必要に応じて)
    ' リムーバブルディスク(2)やCD-ROM(5)など、用途に合わせたガードをかける
    ' DriveType: 1=Fixed, 2=Removable, 3=Network, 4=CD-ROM, 5=Ramdisk
    If drive.DriveType = 4 Or drive.DriveType = 2 Then
        ' 準備完了、安全に操作を開始
        Call PerformFileOperation(objFSO, strDriveLetter)
    Else
        MsgBox "警告: 指定されたドライブはリムーバブルまたは光学メディアではありません。", vbInformation, "タイプ不一致"
    End If

    If Err.Number <> 0 Then
        MsgBox "予期せぬエラーが発生しました: " & Err.Description, vbCritical, "実行時エラー"
    End If
    
    Set drive = Nothing
End Sub

' 実際のファイル操作を行うサブプロシージャ
Sub PerformFileOperation(objFSO, strDriveLetter)
    Dim targetPath, logFile
    targetPath = strDriveLetter & "\WorkLog.txt"
    
    ' ここに実際の業務ロジックを記述する
    ' IsReadyを通過しているため、ここでのアクセスエラー確率は極めて低い
    On Error Resume Next
    Set logFile = objFSO.CreateTextFile(targetPath, True)
    
    If Err.Number = 0 Then
        logFile.WriteLine "操作成功: " & Now
        logFile.Close
        MsgBox "処理が正常に完了しました。出力先: " & targetPath, vbInformation, "完了"
    Else
        MsgBox "ファイル作成に失敗しました: " & Err.Description, vbCritical, "I/Oエラー"
    End If
    
    Set logFile = Nothing
    On Error GoTo 0
End Sub

4. アーキテクトからのアドバイス:さらなる高みへ

このコードを理解した君に、さらに踏み込んだ設計指針を授ける。

ライフサイクルとパフォーマンス

`FileSystemObject` の生成はコストがかかる。ループの中で何度も `CreateObject(“Scripting.FileSystemObject”)` を呼び出すような愚行は絶対に避けること。一度生成したオブジェクトは、プロシージャのスコープ内で使い回し、最後に確実に `Nothing` を代入して解放せよ。

ネットワークドライブへの警戒

`IsReady` はローカルデバイスに対しては完璧に機能するが、ネットワークドライブに対しては、ネットワークの遅延や認証の問題により、判定そのものがタイムアウトを待たされる(ハングアップに近い挙動を示す)可能性がある。ネットワーク越しのリソースを扱う場合は、タイムアウト設計や、事前に `Ping` 等による疎通確認を検討すべきだ。

データベース連携との整合性

もしこのスクリプトが「ファイルのコピーに成功したら、DBのステータスを『完了』に更新する」というフローの一部であるなら、必ず「ファイルの書き込み完了」を確認してからDBを更新せよ。`IsReady` は「書き込みができるか」を保証するものではあるが、「書き込みが物理的に完了したか」を保証するものではない。書き込み直後のファイルクローズを確実に行い、エラーハンドリングを層状に重ねることが、データ整合性を守る唯一の道だ。

結論

`Drive.IsReady` を使うことは、単なるエラー回避のテクニックではない。それは、「ハードウェアという不確実な存在を、ソフトウェアがどうコントロールするか」という設計思想の表明である。

「動けばいい」というコードを書く者は、使い手の信頼を失う。
「失敗を予見し、制御する」コードを書く者こそが、真のエンジニアとして認められるのだ。

タイトルとURLをコピーしました