Win32 ShellExecute系APIの注意点
概要
Win32 ShellExecute系APIは、内部で短時間メッセージループが回るため、思わぬ副作用にご注意という話。
詳細
Win32 ShellExecute系APIは(デフォルトでは)内部で短時間メッセージループが回ります。
すると下記のようなシナリオが起きると、思わぬ動作になります。
- あるダイアログ(やウィンドウ)にボタン押下(WM_LBUTTONDOWN)等のメッセージが飛んでくる。
- 押下イベント(WM_LBUTTONDOWN)等の処理内で ShellExecute系APIを呼びだす。
- ShellExecuteの内部で小さなメッセージループが回る。
- その中で、WM_COMMAND(IDCANCEL)や WM_CLOSE 等が届くことがある(!)
- それら終了系のメッセージコールバック処理が呼ばれる
- ダイアログ(やウィンドウ)が閉じられ、それに紐づけられた this 等が開放される
- ShellExecute系APIを抜ける
- WM_LBUTTONDOWN に紐づけられた hwnd や this が開放済みなことに気づかず、ShellExecute系API行の次行から処理が再開され、エラー or 例外に。
解決
・ShellExecute系を新規スレッドで実行。
(私はこの方式に変更。スレッド先頭で PeekMessage=メッセージキュー作成すると良い)
・ShellExecuteEx系だと SEE_MASK_NOASYNC指定で回避できるかも?(未確認)
備考
IP Messenger でこれが稀に発生していたことに今年(28年ぶり!)気づきました…うーむ。