タスクスケジューラで定期的にスクリプトを実行するバッチ処理の環境を構築していくと、次にリアルタイム処理を実行する環境を整えたくなりました。リアルタイム処理を実行するための条件として特定のフォルダを監視して、当該フォルダにファイルを保存した場合に、ファイル保存をキャッチしてリアルタイムを実行する、という方法があります。
これを実現するのに何か良い方法が無いか調べてみるとPythonのWatchDogや.NETのFileSystemWatcherを利用して構築ができそうです。私は普段Pythonはあまり利用しませんので、.NETをPowerShell経由で利用してファイル監視システムを組む方法を紹介したいと思います。
流れとしては、PowerShellでフォルダ監視用のスクリプトを作成して、このスクリプトファイルをPCスタートアップ時に起動させる、といった事をやろうとしています。
PowerShell FileSystemWatcherファイルの作成
PowerShellでFileSystemWatcherファイルを作成します。最初にスクリプト文を解説した上で、バックグラウンドで実行するための実行ファイル作成方法を説明します。
スクリプト文解説
PowerShellでFileSystemWatcherを利用するスクリプト文を紹介します。スクリプトは、指定フォルダにテキストファイルが保存、変更、削除されるとFileSystemWatcherクラスが保存をキャッチし、ログをテキストファイルに出力する、といった内容になります。
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\ユーザ名\Documents\PowerShell\フォルダ監視" # 監視するディレクトリ
$watcher.Filter = "*.txt" # ファイル名
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
$log_file = "C:\Users\ユーザ名\Documents\PowerShell\フォルダ監視\logfile_監視システム.txt" #ログファイルフルパス
# イベントリスナー
$action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
#Write-Host "$(Get-Date), $changeType, $path"
echo "$(Get-Date), $changeType, $path" >> $log_file
}
# イベントの登録
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) { sleep 5 }
フォルダ監視のスクリプトは一度起動して、常時起動させることが重要です。VSCode(VisualStudioCode)のIDE環境でデバッグ実行する分には常時起動するのですが、VSCodeを閉じるとスクリプトも解除されてしまいます。スタートアップ時にファイル実行でスクリプトを起動させる場合は、最後のwhile文で無限ループさせ、スクリプトを終了させない様にしています。
以下Microsoftのサポートページにクラスの解説やC#による例文が掲載されています。条件を細かく設定する際は、以下サイトを参考にすると豊富な情報が得られます。

Powershell実行ファイルの作成
FileSystemWatcherのスクリプト文をファイル実行する際、バックグラウンドで実行する様にしなければ、デスクトップ上にPowershellの画面が常時出現し続ける状態になります。デスクトップ上に常時起動していることを見たい場合を除き、見た感じも煩わしいのでPowershellファイルをバックグラウンドで実行するショートカットファイルを作成します。
作成したPowershellファイルを右クリックして「ショートカットの作成」をクリック

ショートカットファイルが作成される

ショートカットファイルを右クリックしてプロパティを開く

「リンク先」項目に以下文字列を入力。
pwsh -WindowStyle Hidden -ExecutionPolicy RemoteSigned C:\Users\ユーザ名\Documents\PowerShell\フォルダ監視\ファイル監視.ps1
実行時の大きさは「最小化」を選択し、OKボタンをクリック。この最小化の選択をしなければ、Windows11の場合、バックグラウンドでファイル起動できなくなります。windows10は「通常のウィンドウ」を選択してもバックグラウンドで起動します。

実行ファイルが作成されました。

ファイル名を「file監視」に変更。

OSがWindows11の場合、実行ファイルを「管理者として実行」しなければ、バックグラウンドで実行されない様です。実行ファイルを右クリックして「管理者として実行」をクリックします。

デスクトップ上にPowerShellのターミナルが出現しなければ成功です。実際に監視対象のフォルダにテキストファイルを保存してログが出力されるか確認しても良いと思います。ここではタスクマネージャーでスクリプトが実行されているか確認します。

タスクスケジューラで「pwsh」が出現していれば実行ファイルによる起動が常時されていることになります。
ファイル監視システムのスタート3つの方法
前項でファイル監視を実行するファイル作成まで説明しました。ここでは、ファイル実行ファイル監視を自動的に実行する方法として、PCスタートアップ時に自動的に実行する方法を3つ紹介します。
スタートアップフォルダに保存
PCスタートアップ実行の一番簡単な方法はスタートアップフォルダに実行ファイルを保存する方法があります。この方法ではPCがログオフ状態で動作しません。
スタートアップフォルダは、フォルダアドレス欄に「shell:startup」と入力すると変遷することができます。


PCを再起動させて、スタートアップ時にファイル実行されるか確認します。タスクマネージャーで「pwsh」が出現しているかでファイル実行されているか確認することができます。又は、テキストファイルを監視対象フォルダに保存しログファイルにテキストが追記されるか確認してみても良いです。
Windowsサービスへの登録
Windowsのサービス開始ができる様になればPCスタートアップ時にフォルダ監視のスクリプトを実行する事ができる様になります。PowerShellファイルのexe化 → exeファイルのWindowsサービス登録 といった流れでやりたい事を実現したいと思います。
PowerShellファイルのexe化 IExpress利用
FileSystemWatcerのPowerShellファイルをexeファイル化するためにIExpressというアプリを利用します。このアプリはWindowsに標準で備えられているツールです。Windowsデスクトップ検索でIExpressを入力したり、ファイル名を指定して実行でiexpressを入力してもアプリが出現してきます。以下ではアプリの起動からexeファイルの作成までを紹介します。
「ファイル名を指定して実行」ダイアログを開き「iexpress」を入力。Ctrl+Shift+Enterで管理者権限でアプリを開く。

Create new SelfExtaction Directive fileを選択

Extract files and run an installation command(ファイル解凍+インストールコマンドの実行)を選択

パッケージ名は「ファイル監視」を入力。Windowsサービス登録した際のタイトル名になります。

ファイルインストールの際、確認画面を出現させるか否の選択です。今回はバックグラウンドで実行が主目的ですので、No promptを選択します。

ライセンスの同意の確認画面を出力させるか否かの選択です。Do not display a licenseを選択。

実行したいPowershellファイルを選択します。事前に作成したFileSystemWatcherファイルを選択します。

PowerShell実行のためのコマンドをここで入力します。タスクスケジューラの操作設定と同じ様なコマンドを入力します。install Programは以下の様に入力します。
"C:\Program Files\PowerShell\7\pwsh.exe" -ExecutionPolicy RemoteSigned "C:\Users\<ユーザ名>\Documents\PowerShell\フォルダ監視\ファイル監視.ps1"

プログラム実行時にターミナルの画面設定を選択します。今回はバックグラウンドで実行しますので、Hiddenを選択します。

exeファイル実行終了時のメッセージ画面設定です。No messageを選択します。

保存するexeファイルのディレクトリとファイル名をここで指定します。Browseボタンをクリックして保存したいフォルダ、ファイル名を設定します。

再起動の有無をここで設定します。No restartを選択します。

SEDファイルの保存はしなくてもexeファイルは作成できますので、Don’t saveを選択します。

exeファイル作成の最終画面です。「次へ」ボタンをクリックします。

exeファイル作成に成功したらDone!が表示されます。


Windowsサービスへの登録
Powershellファイルをexeファイル化することに成功できたら、最後にこのexeファイルをWindowsのサービスに登録します。サービス登録するのにコマンドを利用しますので、PowerShellのNew-Serviceメソッドを利用してサービス登録をしたいと思います。
PowerShellを開き、以下コマンドを入力します。
New-Service -Name "FileWatcher" -BinaryPathName "C:\Users\<ユーザ名>\Documents\PowerShell\フォルダ監視\ファイル監視.exe" -DisplayName "ファイル監視" -StartupType Manual -Description "ファイル監視システム"
上記内容の引数を以下にリストアップしてみました。
New-Service
-Name "FileWatcher"
-BinaryPathName "C:\Users\<ユーザ名>\Documents\PowerShell\フォルダ監視\ファイル監視.exe"
-DisplayName "ファイル監視"
-StartupType Manual
-Description "ファイル監視システム"

最後にサービスの開始方法をスタートアップ時に設定します。コンピュータの管理画面からWindowsサービス画面を開き、右クリックで「ファイル監視」サービスのプロパティを開きます。

スタートアップの種類で「自動」を選択→「OK」で終了

最後にPCを再起動させて、タスクマネージャでpwshが起動していればサービス登録が成功しています。サービス登録でファイル実行している場合、ログオフ状態でもシステムが常時起動する事ができます。
タスクスケジューラによる設定
タスクスケジューラのトリガー設定を「スタートアップ時」に設定してPCスタートアップ時にフォルダ監視システムを起動する方法の紹介です。タスクスケジューラ設定の前に電源オプションを変更する必要があります。電源オプションの変更→タスクスケジューラ設定の順番で解説します。
電源オプションの変更
スタートアップ時にタスクスケジューラを起動させるには、電源オプション設定を変更する必要があります。変更内容は、電源オプションの高速スタートアップを無効にします。以下に変更ステップの流れを紹介します。
コントロールパネル→システムとセキュリティ→電源オプション→「電源ボタンの動作を選択する」の順で画面変遷します。

「現在利用可能ではない設定を変更します」をクリック

「高速スタートアップを有効にする(推奨)」のチェックボックスを外し、「変更の保存」をクリック

タスクスケジューラ設定
次にタスクスケジューラの設定方法を紹介します。ポイントは実行ファイルで作成したショートカットファイルの指定方法になります。
「ユーザーがログオンしているかどうかにかかわらず実行する」を選択します。

タスク開始の項目で「スタートアップ時」を選択します。

操作タブの設定例は以下のとおりです。
- プログラム/スクリプト
pwsh - 引数の追加
-Command "C:\Windows\Tasks\フォルダ監視\File監視.lnk"
ショートカットファイルを指定する際は拡張子.lnkを明記 - 開始(オプション)
必要に応じてファイルが保存されているフォルダ名を記入
今回は特に記入しない

タスクスケジューラの全般設定で「ユーザーがログオンしているかどうかにかかわらず実行する」を選択することによって、ログオフ状態でもシステムが常時起動する事ができます。
ログオン状態のみで起動をしたい場合、「ユーザーがログオンしているときのみ実行する」を選択すれば良いのですが、こちらの設定は記事作成時点ではWindows10限定の設定になります。Windows11でログオン状態の起動を選択しても、「起動条件が満たされていません。(イベントID:332)」となり、スタートアップ時の起動が失敗していまいます。他のPC環境では状況が異なるかもしれませんが、記事作成時点で私のWindows11環境ではログオン状態での利用ができない様です。ログオン状態に限定したタスク実行はOfficeVBAを起動させる場合役に立つので、今後良い方法が無いか模索していきたいと思います。現状、ログオン状態で起動させる方法はスタートアップフォルダにショートカットファイルを保存する方法が良いかと思います。
ログオフ状態でPowerShellを起動する方法は以下ページで紹介しています。