前から夏になるとホットフォルダが作りたくなる( 1 | 2 )わけですけれども、それって、ハウス食品が夏だからカレーがどうたらというくらい関連性がない気もします。それはいいとして、どうも今回導入した Linux のファイルサーバには、ホットフォルダを作る機能がついていました。すげー。何がすげーかって、ホットフォルダを一から作るときに悩むことになる、何をトリガーにしてどうやって作業を駆動させるか、ていう問題が解決しているっていうことです。
というわけで使ってみたんですが、ホットフォルダ内にファイルが入ったら、ファイルサーバのサービスで、「ファイルが入った!」というイベントが起き、スクリプトサーバでそのイベントをキャッチして perl スクリプトを起動するという、印刷屋さんは perl ができることがデフォルト、と言っているような男気あふれるシステム。ドイツはちまたに perl 使いがあふれているかもしれませんが、ここは日本なのでこのシステム本当に大丈夫かと思いました。
まあ、perl スクリプトを作るのも結構平気になってきたので、Linux ファイルサーバに入ったファイルを Windows サーバのホットフォルダに転送するホットフォルダを作ってみたんですけれども、どちらかというと、Windows サーバは常に起動しているわけではないので、これは企画倒れです。残念。
印刷関係のサーバプロダクトを作っているところは、たとえばホットフォルダがあらかじめ付いていて、そこにコピーすれば何らかの仕事をして結果を出力するっていうのが多いのかしら、そのくせ、そのプロダクト自身がクライアントになって他所から自分のホットフォルダにファイルを引っぱってくるっていう形態で使おうとすると引っぱるためのツールが OS 任せだったりユーザ任せだったりするのはイカンと思いました。
というわけで、Windows サーバから Linux サーバ上のフォルダを監視して PULL しなくてはいけなくなったのですが、とりあえず調べ物したもののメモ。
職場で使えるソフト [フォルダ監視] [plala.or.jp]
フォルダを監視していろいろしちゃうフリーソフト。これ入れりゃ一発で終わりな案件ですけれども、今回の案件は、Windows サーバはベンダのプロダクトだからソフトの追加はしない方向でということで。残念。
フォルダにファイルが追加されたときに自動的にスクリプトを実行することはできますか:Hey, Scripting Guy! [microsoft.com]
WMI を利用して、WSH で監視。これ結構目から鱗。うちから WSH の本発掘してこようかなあと思いました。しかしどうでもいいのですが、リンク先ページの「Scripting Guys」の意匠が気になります。マッドサイエンティストです。白衣です。どうでもいいですが、理学部の連中は白衣のママ第三食堂に来て飯を食っていたので、一緒に学食で食っているうちらにしたら、どんな汚染物質を食わされていたんだか、たまったもんじゃありませんでした。
というわけで、スクリプトを改造しました。僕は WSH 初心者なんで、適当にやったらとんでもないものができてしまいました。
※ファイルをロストしても当方は責任を持ちません、自己責任で。
その1:つかってはいけないもの
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _
& "Targetinstance ISA 'CIM_DataFile' AND " _
& "Targetinstance.Path = '\\TARGET\\'")
Do
Set objLatestEvent = colFiles.NextEvent
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile objLatestEvent.TargetInstance.Name , "Z:\DESTINATION\"
Loop
すべてのドライブの TARGET フォルダから Z:\DESTINATION フォルダへ移動します。ポーリングの間隔は 10 秒。作ってみたのだけれども、これは危険で、10秒ごとに FDD のアクセスランプがついたりしますし、しかも再起動するまでずうっとついたり消えたりします。よく見ると、WMI に投げている SQL 文が狂気っているようなきもします。せっかく書いたのに! というわけで使用禁止。
その2:未完成だけれども何とか動くよ
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""Y:\\\\TARGET""'")
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
sDataArray = Split(objLatestEvent.TargetInstance.PartComponent, "=", -1, vbTextCompare)
sName = Replace(sDataArray(1), """", "")
Wscript.Echo sName
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile sName , "Z:\DESTINATION\"
Loop
Y:\TARGET フォルダの中に入ったら、Z:\DESTINATION フォルダに移動します。ポーリングの間隔は 10 秒。
これは、まあまあ動くんですが、ホットフォルダに入るファイルの入り方もいろいろあって、そのうちの、ふつーにコピーして入れるパターンだと、コピーに10秒以上かかると、エラーがでます。ダメじゃん。
というわけで、WSH と WMI が得意な人、ご指導ください!