インストーラでカスタム動作を行うためのSetupDLLについてです。
先日、MoonClockをバージョンアップしましたが、これは、S21HTという機種でインストールに失敗するという連絡をいただいたからです。
インストール失敗というか、インストールの最後でウェイトアイコンがグルグル状態のままになるみたい。
手持ちの環境ではまったく発生しないのですが、症状から原因と考えられるのは、CE Setup DLL でやっているToday画面を強制更新する処理。
実は、WMには外部からToday画面を強制更新するAPIは用意されていないんです。
で、よく使われるのが下記の方法。
::SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0xF2, 0);WM_WININICHANGEメッセージをブロードキャスト(すべてのTOPレベルウィンドウへ送信)することで、Today画面を強制更新するわけです。
結構古くから広く使われている方法で、検索すると、たくさんヒットします。
テーマチェンジャなんかにも使われているみたい。
正式な方法ではないとしても、信頼性・安定性は十分に高いと判断してました。
でも、今回の症状をみると、こいつが怪しいじゃないかと考えられるんです。
MoonClockでは、インストール完了時と、アンインストール開始時に、無条件にこいつを呼んでます。
アンインストール開始時には、レジストリを調べてMoonClockがTodayに表示されている場合だけ呼べばいいんですが、これを無条件に呼んでいるのは、誰かがレジストリだけ書き換えちゃうと正しい判定が出来なくなるから。
ちょっと考えすぎな気もしますが、安全側に振ることを考えると、無条件に呼んでおくべきと判断したわけです。
ところが、WM_WININICHANGEメッセージをブロードキャストする方法で固まる環境があるとすると、話は変わってきます。
インストールもアンインストールも、必ず固まることになってしまう。
固まるといっても、相手からの応答を待っているだけで、暴走しているわけではないんですが。
でも、返事がないってことは、メッセージを受け取った相手側がおかしくなっちゃてるんじゃないかっていう心配があります。
調べて見たら、こんな記事がありました。
Sending WM_WININICHANGE message on device with HTC TouchFlo 3D will crash the device
信憑性は定かではないですが、TouchFLO 3D が動いている環境で WM_WININICHANGEメッセージをブロードキャストすると、デバイスがクラッシュするというのです。
俄かには信じ難いんだけど、可能性がある以上、何らかの対策をしなければなりません。
まあ、これが本当だとすると、メッセージを送られてクラッシュするアプリも修正したほうがいいとは思いますが、そうも言ってられません。
そこで、インストーラの安全対策を見直すことにしました。
- レジストリをみて、MoonClockが表示されている場合だけWM_WININICHANGEを送信する。
- ブロードキャストをやめて、GetDesktopWindow APIで取得したToday画面ウィンドウにのみ送る。
- メッセージ送信時タイムアウトの導入。
これらの対策を施した、SetupDLLのソースコード(C++) を晒してみます。
手持ちの環境では問題なく動いていますが、まだ改善の余地があるかもしれません。
情報をお持ちの方がいらっしゃいましたら、何かコメントでお知らせください。
といっても、自分の環境では発生しないので検証しようがないのですが。
3つ目のタイムアウト、
SendMessageTimeout( HWND_BROADCAST,
WM_WININICHANGE, 0xF2, 0, 0, 10*1000, &dwResult);
こんな感じでやってるんですけどね、これでもダメのような…
2つ目のTodayのみにメッセージを送るパターンも、TouchFLOを含むことになるので、あまり効果がないような気もしますし。
ブロードキャストでSendMessage自体、危険な処理にも思えるのですが、どうなんでしょうねぇ。
とりあえず、自分はこんな感じで処理しています。
●アンインストール
直後にインストールが走る場合があるので、Sendのタイムアウトあり
●インストール
インストール後は後に処理が続かないので、Postにして固まらないように
と、しているのですが、どうも駄目な環境があるようです。(そもそも、TouchFLOにメッセージが通知されること自体がダメのような感じ?)
TouchFLOがある時は、更新処理の自動化をあきらめるというのが、いいような気がしてきました。逃げですが。
メッセージボックスを出して、「Todayの設定にて等プラグインを有効にしてください」ってな感じに。
PocketDigitalClockのソース公開されているので、SetUpDllをチェックしてみたのですが、
SendMeesageになってました。
他に、SetUpDllのソース、公開されてないですかねぇ。
ども。
うちでも症状が出ないんですよねぇ。
やっぱり、じゅんたろさんとこも、問題が出てるのは、TouchFLO搭載機ですか?
実は、今回の修正をするときに、最初はTouchFLO 3D がEnableの場合は自動化しないように直したんですよ。
でも、症状が発生している方からの情報では、TouchFLO 3D はOFFだったというので、TouchFLO 3Dを特別扱いしないで、すべての環境でより安全側になるように修正しなおしたんです。
これで駄目なら、
・SendMessageをやめて、PostMessageにする。
SendMessageがまずいのであれば、これで直るはず。
それでも駄目なら、
・TouchFLO 3D インストール環境なら(Enable=0でも)、自動処理はしないでメッセージを出す。
これは、TouchFLO 3D 環境だけに問題があると判断できた場合の対応。
ってな方向で考えてます。
PostMessageにする場合は、以下のようになると思います。
インストール完了時をSendMessageにしているのは、タイムアウトで確実に手動ON指示メッセージを出すためだけなので、
1.PostMessage実行
2.直後に『自動表示されない場合は、設定画面を開いてください』みたいなメッセージを表示。
という方向でいけると思います。
アンインストール時はアンロードされるまで待たなければいけないので、以下のようになると思います。
1.PostMessage実行
2.dllファイルを排他書き込みモードでオープンしてみる。
3.オープンに成功するまで、Sleep(500)を挟みながら2を繰り返す。
Todayが表示されている(dllがロードされている)間は、排他書き込みモードではオープン出来ないんじゃないかという推測に基づいています。
時間がなくて、うまくいくか検証はしてないですが。
機種ごとに事例をまとめているわけではないのですが、S21HT等、Touch Diamond系がよく目についていたような気がします。
ただ、EM-ONEでもインストール時のくるくるが止まらないという話も聞いたことがあるので、原因が突き止められていない状態ですね。(今回の記事とは関係ないことが原因の可能性もあり)
あと、S21HTでも正常にインストールできているというコメントもいただいているのですが、フルフォーマット後、ある操作を行うことでTouchFLOのインストールをキャンセルできるらしくて、環境の絞り込みが難しいです。実機が手元にあれば、いろいろと実験できるんですけどねぇ。
ども。
情報ありがとうございます。
やっぱり、症状が発生する実機がないとこれ以上は厳しいですよね。
今回の対応で安定してくれるといいんだけど。
ネットで調べても、WM_WININICHANGEを使う方法は2003年ごろから紹介されてるし、こちら側では消極的な方法をとるしかないのかも。
最近は、WM_SETTINGCHANGEを使っている記事も見るけど、少なくともWM5/6ではこれは同じものだし。
(#define WM_SETTINGCHANGE WM_WININICHANGE って定義されてる)
まあ、新しいアプリはWM_SETTINGCHANGE使えってことだから、ソースの表記上は、WM_SETTINGCHANGEってすべきだったけど。
情報が集まるまで様子を見るしかないかな。