環境はWinXP+VC7です。
ReadDirectoryChangesWを使って
全ドライブのフォルダの変更を監視したいと思っています。
ReadDirectoryChangesWに設定する監視対象のディレクトリのハンドルは、
CreateFile等で取得するハンドルになりますが、
ドライブが複数あるときや抜き差しされるリムーバブルドライブなども
監視の対象にできればと考えています。
ReadDirectoryChangesWを用いて
デスクトップまたはマイコンピュータ単位で監視することは
可能でしょうか?
よろしくお願いします。
> 全ドライブのフォルダの変更を監視したいと思っています。
やめましょう。
システム負荷がえらいことになります。
レスありがとうございます。
ReadDirectoryChangesWは、ディレクトリ、ファイルなどの
変更を監視するためのものなのでシステムの負荷は高くないです。
単体としての負荷は低くても、まぁ何を監視するのかによりますが、スワップその他
で即座に変更が通知されて結局高負荷になりそうだと思います。
FileMonなどのツールと同様の監視であればかなりきついのでは?
最初に書いたとおり全ドライブのフォルダの変更(作成/削除)を
監視しようと思っています。
Explorerのツリー部分を想定しています。
あれは全体を監視しています。
当然監視自体で高負荷にはなっていません。
SHChangeNotifyRegisterは仮想デスクトップ以下をすべて監視できるのですが、
欠点があるのでReadDirectoryChangesWでできないかなぁと思い質問しています。
フォルダ/ファイルの監視APIは、ファイルシステムから変更通知があるまで
待機するので、監視しているときに負荷はかかりません。
取りこぼしはどうしますか?
コンピュータ内のすべてのファイルとなると相当な数です。
1つのファイルの変更通知の処理が終わらないうちに、別の変更がされたらどうしましょ
う?
Windowsにおいて、変更通知とは、変更を検出するまでスレッドを待たせておくもので
す。
待機スレッドをいくつ作れば、すべてのファイルの変更をもれなく捕まえることができ
るでしょうか?
すいません。負荷とか取りこぼしの話をしているわけではないのです。
私の質問内容と違います。
脱線していませんか?
ちなみに
> コンピュータ内のすべてのファイルとなると相当な数です。
フォルダです。しかも作成と削除のみの監視なのでたかがしれていると思いませんか?
> 待機スレッドをいくつ作れば、すべてのファイルの変更をもれなく捕まえることが
> できるでしょうか?
やってみればわかります。フォルダの監視なので1つで十分です。
ReadDirectoryChangesWは同期/非同期あるのですが、
ワーカースレッドで待とうと思っています。
ただ、実装にもよりますが、全ドライブの監視が一度にできないようなら、
ドライブごとにスレッドを作ろうと思っています。
> フォルダです。しかも作成と削除のみの監視なので
> たかがしれていると思いませんか?
PCの使用状況によっても変わります。
VC等の開発環境をインストールするとフォルダー数もそれなりに増えます。
監視となると状況が変わります。
1秒間隔位のポーリングでよければいいかも知れませんが、常時監視となると別です。
> やってみればわかります。フォルダの監視なので1つで十分です。
> ReadDirectoryChangesWは同期/非同期あるのですが、
> ワーカースレッドで待とうと思っています。
やってみてないみたいですね。
保証がないです。
スレッドは、常時動作していません。
マウス操作等の割り込みが入る都度100ms程度のあきが生じます。
マイクロソフトも承認済みです。
専用のデバイスドライバー、サービスプログラム等を作成し、
システムスレッド上で動かさないと無理だと思います。
それでも常時監視は難しいと思います。下手に作るとOSがハングアップします。
はー。。話が進みません。。。
高負荷だかポーリングだかOSがハングだか知りませんが、
このサンプルを実行してもらえばわかります。
http://www.codeproject.com/file/DirectoryChangeWatcher/CDirectoryChangeWatcher-
05-12-2002_demo.zip
[Directory To watch]にC:\を入力してチェックボックスはすべてONで、
(ファイルやフォルダのファイルサイズや名前の変更等も監視する)
[Start Watch]しても、高負荷にもならなければ、OSもハングしません。
ちなみに、私のPCにはVSをインストールしています。
なにか勘違いしていませんか?
というか、私が質問されて回答しているような。
ReadDirectoryChangesWを使ったことのあるかたから
アドバイスをいただければと思っています。
このサンプルでも「マイコンピュータ」は監視の対象にできず、
「デスクトップ」はDocuments and Settings・・・になってしまうので、
ドライブごとに監視するしかないとは思っています。
ドライブ毎に別スレッドで監視したのでしょうか?
またリムーバルディスクなどの抜き差しはどのように実現できますか?
ReadDirectoryChangesWで監視中はリムーバブルディスクなどの
安全な取り外しができないみたいですね。
ReadDirectoryChangesWは使ったことがないのでこっちだけ
>またリムーバルディスクなどの抜き差しはどのように実現できますか?
SetupDiGetDeviceRegistryProperty
CM_Get_DevNode_Status
CM_Request_Device_Eject
あたりを検索するとサンプルが見つかると思います。
取り外すデバイスの監視を中止してイジェクトしないとだめみたいです。
要DDKです。
デバイスが追加されたりした場合は
Using Hardware AutoPlay
http://msdn2.microsoft.com/En-US/library/aa969332.aspx
を実装するようです。(読んでないので実装方法は不明です)
レスありがとうございます。
> ReadDirectoryChangesWで監視中はリムーバブルディスクなどの
> 安全な取り外しができないみたいですね。
はい。
ReadDirectoryChangesWに渡すため、
CreateFileでディレクトリのハンドル
(この場合はリムーバブルディスクのドライブ)を
開きっぱなしにしなければいけないため、
Windowsに怒られてしまいます。
> 取り外すデバイスの監視を中止してイジェクトしないとだめみたいです。
そうですね。
イジェクトのタイミングでハンドルを開放しようと思います。
サンプルのほうを探してみます。
> イジェクトのタイミングでハンドルを開放しようと思います。
自分で書いておきながら矛盾していますね。
ハンドルを開きっぱなし→安全な取り外しができない→イジェクトがこない
→ハンドルが開放できない→ハンドルが開きっぱなし→・・・
うーむ。。
> 高負荷だかポーリングだかOSがハングだか知りませんが、
> このサンプルを実行してもらえばわかります。
ttp://www.codeproject.com のサンプルだけあってうまく出来ていますね。
「ReadDirectoryChangesW」でこの戻り値を確認して変更ありの場合、メッセ-ジ
をポストします。
ポストされたメッセージを受けてフラグをセットして再び
「ReadDirectoryChangesW」を実行します。
ポストしてメッセージを受けるのに最低でも200mS位掛かります。
よって、最低でも200mS間隔でドライブを監視していることになると思います。
「postMessage」利用してますから、システム負荷も掛かってないと思います。
システム負荷が掛かりそうな場合はOSがポーリング間隔を調整すると
思いますのでそのときは、1S間隔位になるかも知れません。
それでもよければこのサンプルを参考にするのはいいと思います。
>ドライブ毎に別スレッドで監視したのでしょうか?
USB利用したドライブ(メモリー等も含む)のように取り外し自由なドライブには
どう対応しますか?
監視がスムーズでなくなりますが、周期的に繋がっているドライブを調べながら
順次監視していくのがいいと思います。
追記
シュウさんが掲示されたサンプルも短期ならまだしも長期にずっと監視し続ける
となると検討する必要があると思います。
postMessage」利用した方法でなく、きちんとシステム負荷の掛からない時間間隔で
「ReadDirectoryChangesW」を実行するなど検討が必要だと思います。
また、サンプルは1ドライブだけですが、全ドライブとなるとまた1ドライブ・
1ドライブをどのように監視していくかが問題だと思います。
ぬさんが紹介している「FileMon」というツールも実際に実行して見るのもいいと思いま
す。