2009年02月13日
_ [TTBase] 倉庫(仮)さんとこの「TTBaseのソース」を読んで。
TTBase本体についていろいろ意見を頂いたので、ちょっと考えてみました。
InitでExecuteCommandを使う問題については、実際にコマンドを実行しているTPlugin.DoCommandでLoadしていなければLoadする(Initを行う)ということをしているので問題にならないはずです。 また、そもそも非常駐型のプラグインであれば、コマンド実行毎にInit→Execute→Unloadしているので、それも問題にならないです。 ただ、TTBase.datにまだ入っていない(新規にプラグインを追加した)場合、そもそもプラグインリストに追加されていない可能性があるわけで、そうなるとプラグインが見つからずに結局そのコマンドが実行されないだけ、ということが起こりえそうです。 それはそれで気付き辛い問題となりそうなので、プラグインの探索とInit処理は別タイミングにした方がいいかもしれませんね。一度プラグインリストを完成させてから、各プラグインのInit処理を呼び出す、と。
そういえば、今の話とはあまり関係ないけど、プラグインAのInitでプラグインBのコマンドを呼び出している場合に、プラグインBのInitでもプラグインAのコマンドを呼び出していたりすると(循環していると)無限ループに陥ってしまいそうです。 何らかの対処を考える必要があるかなぁ。。。 どうしたらいいかは思いつかないのだけれど。
とりあえずInitはこれでよいとしても、UnloadでExecuteCommandを使うと、せっかくUnloadした他のプラグインがまたLoadされてしまってリソースリークとか起こしてしまいそうですね。 Unload後に本当にUnloadされているかもう一度確かめた方がよいのかもしれません。 …それはそれで先に書いたように無限ループの可能性が残っちゃうのか。
なんか、いろいろと悩ましいです。
フックインストールとプラグインロードの順序については確かに指摘の通りですね。これは直すべきでしょう。
TTBEvent_FreePluginInfoについては、メモリを確保した人が解放すべき、という意味でも、このまま残しておきたいところです。 ただ、省略されたプラグインがあってもよいように拡張するのはありかもしれませんね。
_ [TTBase] プラグインのロードとフックインストールの順序。
以下の2つのテスト用プラグインを作成して検証してみました。
- Init時に5秒間だけ待機(Sleep)する、1st.StartWait.dll
- Init/Unload/Hookの各メソッドでログを出力するだけの、2nd.OutputLog.dll
こうすることで1st.StartWait.dllをロードしている間に2nd.OutputLog.dllのHookが呼ばれちゃうかなーと思ったのですが、結論としてはInit前にHookが呼ばれることは無かったです。 TTBase.datによるプラグイン情報のキャッシュがされている場合、されていない場合のそれぞれで確認しています。
で、改めてTTBaseのソースを確認したのですが、今のつくりのままでも問題なさそうなことが分かりました。 まず、フックしたメッセージがTTBaseに届くと、各プラグインのTPlugin.DoWindowHookが呼ばれます。この中ではTTBEvent_WindowsHookの関数アドレスを取得していれば(GetProcAddressしていれば)その関数を呼び出すようになっています。 では、TTBEvent_WindowsHookの関数アドレスを取得しているタイミングがどこかというと、TTBEvent_Initの呼出に成功した後(TPlugin.Load内)なんですね。んで、TTBEvent_Unloadしたら関数アドレスのクリア&DLLの解放をしています。 なので、InitしてからUnloadするまでの間しかTTBEvent_WindowsHookは呼ばれないようになっていました。
ということで、InitとHookの関係は今のままでも問題なし、という結論になります。
…が、プラグインがロードできていないタイミングでフックを開始するのは順序としてどーなの?という気はするので順番を入れ替えておいた方がよいですかねぇ。。。
_ [TTBase] メモリ使用量の削減。
TTBase.exeと同じ位置にTTBase.icoを配置するとそのアイコンを読み込む、という仕様があるのだけれど、このアイコンがあるかないかでメモリ使用量にかなり差があったので、いろいろ調べていました。 私の環境(WinXP + TTBase v1.1.0 beta1)でまったくプラグインがない状態で試したところ、TTBase.icoなしの場合は約8MB、TTBase.icoありの場合は約4.5MBほど使用しています。
TTBase.icoがない場合にデフォルトアイコンを取得するため、SHGetFileInfo APIを使用して自分自身のexeファイルからアイコンを読み込んでいるのですが、その処理があるとメモリ使用量が増えてしまうようです。
ということで、デフォルトアイコンの取得方法を変更した版を作ってみました。
他の環境でも有効であれば本体に取り込みたいので、試してもらえると嬉しいです。(→ttb10100b2pre.zip)
_ U [はじめまして、Uです >コマンド実行毎にInit→Execute→Unloadしている ソースを改めて見たら、おっ..]
_ ももたろ [ツッコミありがとうです。 疑問が氷解したようでなによりです。 …とはいえ、指摘してくださった点で、直した方がよりよ..]