【UiPath】ファイル変更トリガーを改めて…

## 皆もすなるQiitaといふものを、儂もしてみむとてするなり。

と言う訳で、こん＊＊は！はなっち！です。

【初めに】
UiPathに初めて触れた2018年春。とにかくいろんなアクティビティをmain.xamlにドラッグ＆ドロップして、こんな事が出来る！これは、こうなるんだと勉強したものでした。

その中で、？？？だったのは、「ファイル変更トリガー」でした。

読んで名のごとく、「ファイル」の「変更」をスコープして、変化があれば、それを「トリガー」とするものなのですが...

時代は2023年。あれから5年。

今回は、その「ファイル変更トリガー」を改めて…
- - - 
## １）「ファイル変更トリガー」アクティビティの今。
余り意識していなかったのですが、Global MVPの末武さん(@SuetakeYoichi)の記事が詳しいですね。

https://qiita.com/SuetakeYoichi/items/775d42a9ae2707374615

色々とUiPath開発の現場でも、ユーザの意見をFEEDBACKして、よりいいものを開発している！って事ですね。と言う事は、今後もバージョンアップがあるかもしれませんね。

## ２）「ファイル変更トリガー」アクティビティの配置
記事にするにあたっての環境は、以下の通り。
* アクティビティパックは、"UiPath.System.Activities": "[23.4.1-preview]"
* Studioは、"studioVersion": "23.4.0.0"

今回は、FileChangeTriggerV3（第三世代）でのお話。
「ファイル変更トリガー」アクティビティは、単独で機能する事はできず、「トリガー スコープ」の中で機能するものです。

### 2-1「トリガー スコープ」アクティビティ
「トリガー スコープ」アクティビティは、一連のトリガー系アクティビティの親です。「トリガー スコープ」アクティビティの「トリガー」部分に、「ファイル変更トリガー」を配していくわけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/b6c6f73b-f623-4378-bbb8-bde0307cfb13.png)

「トリガー スコープ」アクティビティには、「スケジューリング モード」と言うプロパティがあり、そこには、３つの選択肢があります。
* 順次：監視トリガで検出した変更（通知フィルタ）を、アクティビティ単位で、シーケンシャルに、アクションへ制御を渡し、次の検出処理に戻る。
* 同時：監視トリガで検出した変更（通知フィルタ）を、変更単位で、シーケンシャルに、アクションへ制御を渡し、次の検出処理に戻る（再現確認中）。
* 一回：監視トリガで検出した変更（通知フィルタ）を、アクションへ制御を渡し、次の検出処理に戻らずにスコープを抜ける。

「トリガー スコープ」アクティビティを配した時点では、「順次」が選択されています。

### 2-2「ファイル変更トリガー」アクティビティ
「ファイル変更トリガー」アクティビティを、その親である「トリガー スコープ」アクティビティに配してみました（ここでは必須設定パラメタに設定がないエラーが現れています）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/8de83379-6360-c98b-d414-c94f40f06af1.png)

「ファイル変更トリガー」アクティビティには、監視する「変更の種類」と言うプロパティがあり、そこには、４つの選択肢があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/637a633a-2f94-b139-cca9-e5538d0ba56f.png)
* Created：ファイルが新たに作成された時に通知される。
* Deleted：ファイルが削除された時に通知される。
* Changed：ファイルに変更があった場合に通知される。変更を監視するのは、通知フィルターで指定する。
* Renamed：ファイル名が変更された時に通知される。その際、旧ファイル名は、OldFullpathで取得できる。
* All：上記すべてをチェックONとする。

更に、「ファイル変更トリガー」アクティビティには、「通知フィルター」と言うプロパティがあり、そこには、８つの選択肢があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/570189b7-7f26-c37b-81f7-307d20b540c3.png)
* FileName：ファイル名の変更時を通知
* DirectoryName：監視中のフォルダ名の変更時を通知
* Attributes：ファイルの属性変更時を通知
* Size：ファイルのサイズ変更時を通知
* LastWaite：ファイルの最終更新日変更時を通知
* LastAccess：ファイルの最終参照日変更時を通知
* CreationTime：ファイルの作成日時変更時を通知
* Security：ファイルのアクセス権の変更時を通知

「ファイル変更トリガー」アクティビティを配した時点では、「Changed」、「FileName」が選択されています。

## ３）「ファイル変更トリガー」アクティビティの動作結果の情報
トリガー発動した時、その情報は、アクションで宣言されているUiPath.Core.Activities.FileChangeTriggerArgs型の"args"に渡されます。
この変数に内包されているプロパティを参照し、後続の処理にて利用します。

|argsプロパティ|説明|
|:-|:-|
|.FileChangeInfo|ファイルが変更された時の情報が格納される(別表説明)|
|.TriggerName|ファイルの変更を検出した[ファイル変更トリガー]の表示名|
|.TriggerType|ファイルの変更を検出した[ファイル変更トリガー]のタイプ（.Nameで、"FileChangeTriggerV3"が得られる）|

|FileChangeInfoプロパティ|説明|
|:-|:-|
|.ChangeType|ファイルに変化があった時の種類が格納される(別表説明)|
|.FullPath|ファイルに変化があった時の、そのファイルのフルパスが格納される|
|.Name|ファイルに変化があった時の、そのファイル名が格納される|
|.OldFullPath|ファイルが改名された時の、そのファイルの改名前のフルパスが格納される()|
|.OldName|ファイルが改名された時の、その改名前のファイル名が格納される|

|ChangeTypeが取りうる値|説明|
|:-|:-|
|Created|ファイルが新たに作成された|
|Deleted|ファイルが削除された|
|Changed|ファイルが変更された|
|Renamed|ファイル名が変更された|


## ４）「ファイル変更トリガー」アクティビティの動作確認の準備
### 4-1「トリガー スコープ」アクティビティのパラメタの設定
「トリガー スコープ」アクティビティの「スケジューリング モード」に、「順次」を設定します。「順次」での動作確認後、「同時」⇒「一回」に設定を変えていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/6d8d04a1-a16c-fa96-430c-55023749e5b6.png)

### 4-2「ファイル変更トリガー」アクティビティのパラメタの設定
「ファイル変更トリガー」アクティビティのパラメタに、値を設定します。
* 「パス」には監視するフォルダパスを指定します。
　検証では、[C:\USERS\HANACCHI\DESKTOP\検証\ファイル監視トリガー]を設定します。
* 「ファイル名フィルター」には、"*.txt"とか、"*.xlsx"とか。無指定も可能です。
　検証では、二つの「ファイル変更トリガー」を配し、それぞれに、"*.txt"、"*.xlsx"を設定します。
* 「サブディレクトリを含む」には、True/Falseを指定します。
　検証では、"False"とします。

今回の検証では、監視するフォルダパスに、ファイルがコピー/移動された時の挙動を調べるために、何が何でも拾えるように、以下のように設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/9dc18f01-9c19-e98b-d8d2-1ce54fc5dfe8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/bfb3db82-e4d4-bfb4-c2d1-492617a5c12a.png)
「トリガー スコープ」アクティビティの「スケジューリング モード」を変更させて動作確認するので、ここの設定は変えません。

### 4-3 「ファイル変更トリガー」アクティビティでのトリガー発生時のアクション
ここでは、どのような変更の種類を検知したのかと、そのファイルの情報を「Write Line」アクティビティでログ出力する事にしました。以下は、そのロジックの画像イメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/c79e16a1-5f4a-8fbf-9068-81c949d6e3ea.png)

### 4-4「ファイル変更トリガー」アクティビティの検証環境
【フォルダ/ファイル】は、以下のようにしています。
```
> tree /f "C:\Users\HANACCHI\Desktop\検証"
C:\USERS\HANACCHI\DESKTOP\検証
│  新規 Microsoft Excel ワークシート.xlsx　　← A1セルに時刻
│  新規 テキスト ドキュメント.txt　　　　　　← 文字列+時刻
│  新規 テキスト ドキュメント_New.txt　　　　← 文字列
│
└─ファイル監視トリガー
        新規 テキスト ドキュメント.txt　　　　← 文字列
```
「ファイル監視トリガー」フォルダ中の`新規 テキスト ドキュメント.txt`を作成し、そのファイルを上位フォルダにコピーし、コピー先の`新規 テキスト ドキュメント.txt`に時刻を追記し、最終更新日を変えるようにしています。
```
 C:\Users\HANACCHI\Desktop\検証 のディレクトリ
2023/04/08  12:15    <DIR>          ファイル監視トリガー
2023/04/07  14:44             8,568 新規 Microsoft Excel ワークシート.xlsx
2023/04/08  12:15                27 新規 テキスト ドキュメント.txt
2023/04/08  12:15                34 新規 テキスト ドキュメント_New.txt

 C:\Users\HANACCHI\Desktop\検証\ファイル監視トリガー のディレクトリ
2023/04/08  12:15                 6 新規 テキスト ドキュメント.txt
```
Dirコマンドの時刻表記が時分なので差はわかりませんが、ファイルサイズが違っている事で追記している事とします。
### 4-4「ファイル変更トリガー」アクティビティが反応するアクション
監視フォルダには、一つのファイル`新規 テキスト ドキュメント.txt`を存在させておきます。
監視外フォルダには、`新規 Microsoft Excel ワークシート.xlsx`、`新規 テキスト ドキュメント.txt`、`新規 テキスト ドキュメント_New.txt`が存在します。

この監視外フォルダに存在する3つのファイルを、手作業で、監視フォルダにコピー/移動させます。`新規 テキスト ドキュメント.txt`は上書き確認ダイアログが表示されるので、「ファイルを置き換える(R)」で応えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/aba135f0-8b66-bfa3-1790-a0e89f967589.png)



## ５）「ファイル変更トリガー」アクティビティの動作確認
ロボットの先頭には、「4-4「ファイル変更トリガー」アクティビティの検証環境」で記述したファイル構成を生成するロジックを組み込んであり、その生成が完了したのち、「ファイル変更トリガー」アクティビティで監視フォルダ中の変化を監視させるロジックとしました。

｛`順次`,`同時`,`一回`｝×{`COPY`,`MOVE`}の組み合わせで都合6回実行させました。

その結果をまとめると、以下のようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/4b28fa08-65f0-f55c-2f86-936d89f887b6.png)

【結果】
* スケジューリング モードが`一回`の場合は、いずれかの事象が発生したら直ちにトリガーが発動され、「トリガー スコープ」から抜ける。
* `順次`と`同時`とでの差は見られなかった。しかし、`順次`と`同時`があるのだから、ロボットの設定、検証の方法に至らぬ箇所があったに違いない。
* `COPY`と`MOVE`で明確に違うのは、`MOVE`の場合は、既存ファイルを一度`Delete`してからと言う事である（上表赤字部分）。まず`Delete`し、続けて新たにファイルを`Create`し、移動後にファイルのプロパティを改めて設定(`Change`)していると考えられる。

## 【まとめ】
* 実際の業務のキッカケとしては、監視フォルダに対して、ファイルを格納する行為であろう。その行為が、`ファイルをコピー`あるいは`ファイルを移動`するであっても正しく検知できなければならない。
* `ファイル名のリネーム`、`ファイルの削除`もキッカケとする業務は、同じ「トリガー スコープ」アクティビティの中に、別の「ファイル変更トリガー」アクティビティをドラッグ＆ドロップし、トリガーされた時の`argsTriggerName`で検出したアクティビティの`表示名`で起動する処理を制御する。
* `順次`あるいは`同時`の場合は、「通知フィルター」の設定で想定された変化でトリガーが発動しない事もあるかもしれない。「通知フィルター」ですべての変化を通知するようにすると、同じファイルに対して、何度もアクションが発生してしまう。
これに際しては、List型変数に「リストに項目を追加」アクティビティで、一時検知したファイル名(`args.FileChangeInfo.Name`)を追加する。トリガー発動された際に、検知したファイル名(`args.FileChangeInfo.Name`)が、List型変数内に存在するかのチェックを行い、既に処理済かの判断を行ったりするのも一考であろう。
* 先のList型変数でのチェックでは、毎回同じファイル名での業務である場合には有効ではない。この場合は、トリガー発動したら、検知したファイル名(`args.FileChangeInfo.FullPath`)を監視フォルダ外のフォルダに移動してしまう。そのファイルに対して再びトリガー発動された際には、既にそのファイルはないはずなので、処理は行わない（`System.IO.File.Exists(args.FileChangeInfo.FullPath)`で判断)。
* ファイルを`MOVE`した際にまず`Deleted`で検知されるのには驚きを隠せない。Exploereのファイル関連プログラムの仕様なのでしょう。例えば、OSとか、コピー/移動するプログラムによって、その挙動は違うものと考えると、「ファイル変更トリガー」アクティビティを使いこなすには、業務運用も考えつつ、十分な検証を地道に積み上げていかなければならないと思う。

- - - 

##おわりに
いかがでした？

今回も読んでいただきありがとうございました！
是非UiPathでのロボ開発の一助になればと思っています。

ありがとうございました！