PowerShell + WPF + FileSystemWatcher ― ファイル変更イベントを画面で観察する

PowerShellカテゴリを表すパンダのイラスト PowerShell

この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。.NET FileSystemWatcherとWPF Dispatcherの公式仕様を確認し、ダミーフォルダの変更イベントを画面へ表示する最小構成に整理しています。

検証ステータス:📘 Microsoft公式仕様確認済み・Windows実機未確認

FileSystemWatcherのイベントをWPF画面へ出すTRYでは、見た目より先に「イベントが来た」「UI threadへ渡せた」を確認します。

今回、ダミーファイル作成後に画面へCreatedまたはChangedが表示されればTRY成功です。

Smoke Testの構成

TEMP\Papanda-FileWatcher-Demo
  ↓ FileSystemWatcher
Created / Changed / Deleted / Renamed
  ↓ ConcurrentQueue
DispatcherTimer
  ↓
WPF ListBox

PowerShellではWatcherのPathを専用ダミーフォルダへ限定し、IncludeSubdirectories = $falseにします。

イベントハンドラーからWPFコントロールを直接更新するのではなく、まずイベント情報をキューへ積み、UI thread側のDispatcherTimerで取り出す形にすると「イベントを受ける場所」と「画面を触る場所」を分離できます。

Observe

最小版では、監視開始後にダミーのtest.txtを作ります。時刻、イベント名、ファイル名だけを表示し、ファイル内容は読みません。

再利用版には「テストファイルを作る」ボタンを付けました。監視対象もユーザーのTEMP配下だけなので、本番共有フォルダをいきなり指定せず挙動を確認できます。

1か所変えてみる

既定Filterは *.txt です。Daily-Code-Samples版では次のように1か所だけ変えられます。

.\Show-FileEvents.ps1 -Filter '*.csv'

TXTとCSVで表示対象がどう変わるかを見ることで、Filterの役割を確認できます。

なぜ複数回になるのか

アプリの保存処理は「1回の保存=1イベント」とは限りません。テンポラリ作成、書き込み、rename等が組み合わさることがあります。そのため実務版ではdebounceや重複抑制が必要です。

ここがFileSystemWatcherを単なる「フォルダにファイルが来たら処理する機能」と覚えるより重要なところです。イベントは処理開始のヒントにし、実ファイルの状態は処理側で改めて検証します。

Failure / Boundary

イベントは取りこぼしや重複を前提に設計します。WatcherをDBの完全な監査ログの代わりにはしません。

Daily-Code-Samples版では画面終了時に EnableRaisingEvents = falseDispose()DispatcherTimer.Stop() を行います。GUIを閉じたあとも監視オブジェクトを残さないためです。

仕事で使うなら

共有フォルダへ届くCSVを「処理開始のきっかけ」として検知し、実処理側でファイルの存在・サイズ安定・拡張子・再処理防止を改めて検証する構成にできます。

事務職向けの小さな社内ツールなら、CSV到着を画面へ表示する、定型ファイルの受信状況を見える化する、といった入口にもできます。ただし本番自動処理へ進む前に、重複イベントと書き込み途中のファイルを必ず考慮します。

公式情報

  • Microsoft Learn: FileSystemWatcher

  • Microsoft Learn: Dispatcher

GitHubサンプル

文書情報

記事タイトル
PowerShell + WPF + FileSystemWatcher ― ファイル変更イベントを画面で観察する
作成日
更新日
Source URL
https://papanda925.com/?p=16191

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

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