【入門編】VB.NETで実現するファイル監視自動化:FileSystemWatcherを用いたリアルタイムログ解析とUIスレッド安全通知 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

こんにちは!エンジニアリングの世界へようこそ。
マクロの記録や、決まりきった手順の自動化から一歩踏み出し、「自分の手で本格的なデスクトップアプリケーションを作りたい」そう思っているあなたへ。

今回は、業務自動化の現場でよくだいご味となる「ファイル監視自動化:FileSystemWatcherを用いたリアルタイムログ解析とUIスレッド安全通知」をテーマに、VB.NETの極意を伝授します。

「社内サーバーに新しいCSVやログが上がったら、自動で画面のグリッド(一覧表)を更新したい」
そんな現場の要望をスマートに解決する技術です。ここをクリアすれば、VB.NETによるイベント駆動UI開発の基本と、マルチスレッドの壁はバッチリですよ!

—

1. なぜ「ファイル監視」でつまずくのか?(心構えと基本)

フォルダの中身を監視するクラスとして、VB.NETには `System.IO.FileSystemWatcher` が用意されています。これを使えば、ファイルが「作成された」「変更された」「削除された」といったイベントを捉えることができます。

しかし、ここにプログラミング初学者が9割がたハマる「魔の罠」があります。

それは、「ファイル監視イベントは、UI(画面)とは別のスレッド(バックグラウンド)で突然発生する」という点です。
バックグラウンドスレッドから、直接画面のDataGridViewなどを操作しようとすると、VB.NETでは容赦なく以下のようなエラー(例外)が発生してアプリが強制終了します。

> 「クロススレッド操作が有効です: コントロールが作成されたスレッド以外のスレッドからコントロールがアクセスされました。」

この壁を美しく乗り越える方法こそが、今回マスターする最大の肝です。優しく、かつ本質的に解説していきますね。

—

2. アプリケーションの設計図

今回は、以下のようなシンプルなWindows Formsアプリケーションを作ります。

1. 画面(Form1):監視開始ボタン、停止ボタン、結果を表示するグリッド(`DataGridView`)を配置。
2. エンジン(`FileSystemWatcher`):指定フォルダを監視し、ファイル変更を検知。
3. 安全通信(`Invoke`):別スレッドから安全にUIスレッドへデータを引き渡す。

—

3. 実装コード:実務でそのまま使える堅牢なクラス

Visual StudioでWindows Formsアプリ(VB.NET)を新規作成し、フォームにボタン(`btnStart`)とグリッド(`DataGridView1`)を配置してください。

そして、フォームのコード(`Form1.vb`)を以下のように書き換えます。
プロの現場で通用するよう、リソースの解放や例外処理、スレッド安全性を網羅した実装にしています。

Imports System.IO
Imports System.Text

Public Class Form1

‘ ファイル監視を行うクラスのインスタンス
Private WithEvents LogWatcher As FileSystemWatcher

‘ 監視対象のフォルダパス(実際の環境に合わせて変更してください)
Private ReadOnly TargetFolder As String = “C:\SharedLogFolder”

Private Sub Form1_Load(sender As Object, e IsNot Nothing) Handles MyBase.Load
‘ グリッドの初期設定
DataGridView1.ColumnCount = 2
DataGridView1.Columns(0).Name = “検知時刻”
DataGridView1.Columns(1).Name = “ファイル名 / 内容”
DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill

‘ ボタンの初期状態
btnStart.Enabled = True
End Sub

‘ 【監視開始ボタン】
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
‘ フォルダが存在するかチェック
If Not Directory.Exists(TargetFolder) Then
MessageBox.Show(“監視対象のフォルダが存在しません: ” & TargetFolder, “エラー”, MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If

‘ FileSystemWatcherの初期化
LogWatcher = New FileSystemWatcher()
LogWatcher.Path = TargetFolder
LogWatcher.Filter = “.csv” ‘ CSVファイルのみを対象にする
LogWatcher.NotifyFilter = NotifyFilters.LastWrite Or NotifyFilters.FileName

‘ イベントハンドラの有効化
LogWatcher.EnableRaisingEvents = True

btnStart.Enabled = False
Me.Text = “ファイル監視中… [” & TargetFolder & “]”
End Sub

‘ 【ファイル変更検知イベント(※別スレッドで動きます!)】
Private Sub LogWatcher_Changed(sender As Object, e As FileSystemEventArgs) Handles LogWatcher.Changed
‘ ファイルが更新された瞬間にここが呼ばれます。
‘ ※注意:ここではまだ画面(DataGridView)を直接触ってはいけません!

Dim fileName As String = e.Name
Dim detectTime As String = DateTime.Now.ToString(“HH:mm:ss”)

‘ 安全にUIスレッドへ処理を委譲(クロススレッド対策)
If Me.InvokeRequired Then
‘ 別スレッドから呼ばれた場合、UIスレッドに処理を投げ直す
Me.Invoke(New Action(Sub() AddLogToGrid(detectTime, fileName)))
Else
‘ 万が一UIスレッドから呼ばれた場合はそのまま実行
AddLogToGrid(detectTime, fileName)
End If
End Sub

‘ 【UIスレッド安全にグリッドへデータを追加するメソッド】
Private Sub AddLogToGrid(detectTime As String, fileName As String)
‘ この中は安全に画面を操作できるUIスレッドです
DataGridView1.Rows.Add(detectTime, fileName & ” が更新されました。”)

‘ 最新行にスクロールさせる親切設計
If DataGridView1.Rows.Count > 0 Then
DataGridView1.FirstDisplayedScrollingRowIndex = DataGridView1.Rows.Count – 1
End If
End Sub

‘ 【アプリ終了時のクリーンアップ(資源の解放)】
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If LogWatcher IsNot Nothing Then
LogWatcher.EnableRaisingEvents = False
LogWatcher.Dispose()
End If
End Sub

End Class

—

4. コードの深掘り解説:ここがエンジニアの腕の見せ所

① `WithEvents` とイベント駆動の魔法

`Private WithEvents LogWatcher As FileSystemWatcher`
`WithEvents` キーワードを使うことで、VB.NETでは面倒なイベント接続のコードを書かなくても、Handles句を使って「そのオブジェクトが発火するイベント」を直感的に捉えることができます。これがVB.NETの非常にエレガントなところです。

② なぜバグる? `Me.InvokeRequired` の正体

If Me.InvokeRequired Then
Me.Invoke(New Action(Sub() AddLogToGrid(detectTime, fileName)))
Else
…

ここが今回の最重要ポイントです。
`InvokeRequired` は、「今のこのコード、画面を作った主(UIスレッド)以外の奴が動かしてないか?」を判定するプロパティです。もし別スレッド(番人)であれば、`Me.Invoke` を使って、「主よ、代わりにこの仕事(`AddLogToGrid`)をやってくれ!」と安全に頼み込む(委譲する)わけです。
これを理解しているだけで、Windows Formsアプリの安定性は劇的に向上します。

③ 忘れちゃいけない `Dispose`(オブジェクトのライフサイクル)

アプリを終了するとき、OSのファイル監視リソースが中途半端に残ると、メモリリークやフォルダがロックされたままになる原因になります。
`FormClosing` イベントでしっかりと `LogWatcher.Dispose()` を呼び出し、後片付けを徹底する。こういう細やかな気配りが、プロとアマを分ける境界線です。

—

5. まとめ

今回は、`FileSystemWatcher` を用いたリアルタイムなファイル監視と、Windows Formsにおけるマルチスレッド制御(クロススレッド対策)を解説しました。

  • ファイル監視は別スレッドで動く!
  • 画面を触るときは `Invoke` を使ってUIスレッドへバトンタッチする!
  • 使い終わったリソースは必ず解放する!

この3つさえ押さえておけば、業務を劇的に効率化する「生きた自動化ツール」を自由自在に作り出すことができます。

マクロの記録を卒業したあなたなら、もう立派な自動化エンジニアの卵です。ぜひ社内のシステムや、自身の検証環境でこのコードを動かしてみてください。「おっ、動いた!」という感動が、次のスキルアップへの最高のガソリンになりますよ。

それでは、次回の極意でお会いしましょう!

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