2019年07月12日

恥ずかしがり屋のエラーダイアログ

ListView to CSVで、データ保存中に連続でエラーが発生した場合、妙な挙動が起こることが分かりました。

連続でエラーが発生する場合……というか、データ保存が失敗するときは、書き込み失敗なので、だいたい連続で発生するわけですが、ある程度は前面に出てきていたエラーダイアログが、ある時点から急に背後に隠れ始めます。

201907_hazukashi1.jpg
エラーダイアログが連続で何回も発生するので[OK]を押し続けていると、
201907_hazukashi2.jpg
急に後ろに隠れだす。

どうやら、親ウィンドウのWM_DESTROYが子ウィンドウに伝播して、子ウィンドウでWM_DESTROYが発生していることによる発生するようです。
ListView to CSVは少し特殊な作りをしており、各ウィンドウごとに保持するデータは、そのウィンドウが破棄されるタイミングで保存されます。なので、WM_DESTROYが伝播するときは、それぞれのWM_DESTROYごとにデータ保存が実行されます。

これであちこちのウィンドウごとに(しかも破棄されながらの状態で)メッセージボックスを出すと、こんな感じでおかしなことになるらしい。

状況によっては、背後に隠れたことがユーザーから認識できず、終了できなくてユーザーが混乱することになりかねないので、何らかの対応を行おうかと思います。

メッセージダイアログをTOPMOST(最前面)指定にしてしまうとか。


続きを読む
posted by ayacy at 23:23 | Comment(0) | TrackBack(0) | プログラミング

2019年07月04日

Windows APIのRegisterHotkey()って、仕様変更したのかな?マウスのお供の挙動に違和感が。

マウスのお供で、新しく追加したホットキーの機能をいじっていた時、ふと、ホットキーの割り当てを起動中に変えた場合に、古いホットキーが無効にならないことに気づきました。

例えば、「ON/OFFの切替」をCtrl+Alt+Aに割り当てた後、起動したままCtrl+Alt+Bに割り当て直した場合、Ctrl+Alt+ACtrl+Alt+Bの両方で「ON/OFFの切替」が行われてしまう状況になりました。
201907_mtmohotkey.png

ホットキーの割り当ては、Windows APIのRegisterHotkey()を用いて行っています。
このAPIを使った機能を初めて実装したのは、かなり前のことになりますが……、Windows APIのRegisterHotkey()って、最近、動きが変わったのかな?

昔、使った時は、2回目の呼び出しで同じウインドウハンドルとIDを指定したら、前に指定したホットキーは自動解除されたと思うし、MSDNに書いてある解説でもそう解釈できます。

RegisterHotKeyDocJa.png

ただ、手元のWindows 10で試したら、そうはならずに1回目のRegisterHotkey()で同じハンドル、同じIDで登録した古いホットキーも有効なままになっているような動きになっています。

登録前に一旦、UnregisterHotkey()を呼び出しておけばそうはならないんですが………、昔からそうだったっけか?
昔からそうで、単なる僕の勘違いなら、プログラムを直せばいいのだが、その場合MSDNの記述が怪しいことになる。もし、最近のWindows 10の不良または仕様変更なら、OSごとに影響を調べて、場合によってはOSごとの処理分けを書く必要が出てきて面倒なことになる。

「猫でもわかるプログラミング」の第193章のホットキーを扱った項でも、ホットキーの変更でUnregisterHotKey()を呼び出している様子はない。


どっちだろう?

と思って、最新の?英語ドキュメントを調べたら、「…maintained along with the new hotkey.」(新しい設定とともに保持される)と書いてある!!

RegisterHotKeyDocEn.png

どうやら、Windows Server 2003までの挙動(重複設定時は自動解除)と、最近のWindowsの挙動(重複設定時は両方保持)では、仕様が異なっているということらしい。

うーむ、ホットキーの変更前にUnregisterHotkey()を挟むように、マウスのお供他を修正せねば…。


posted by ayacy at 00:00 | Comment(0) | TrackBack(0) | プログラミング

2019年06月29日

新PCでVisual Studio 2010を動かしたら、謎のエラーが出てIntelliSenseが効かなくなった

一昨日、新環境でのVisual Studioの動作確認を兼ねて、マウスのお供の最新β版を公開したことについて取り上げましたが、この際に、新PCでVisual Studio 2010を動かしたら、謎のエラーが出てIntelliSenseが効かなくなるという現象に見舞われました。

Visual Studio 2010を立ち上げて、エディタ上で何かしらの文字を打ち込むと、高確率で次のようなエラーメッセージが表示されます。

201906_vs2010_err1a.png
Visual Studio は例外を検出しました。拡張機能が原因である可能性があります。
 詳細な情報を得るには、コマンド ラインで /log パラメーターを指定してアプリケーションを実行し、'C:\Users\○○\AppData\Roaming\Microsoft\VisualStudio\10.0\ActivityLog.xml' ファイルを調べてください。

拡張機能などと言われても…まだ、Visual Studio 2010をインストールしたばかりであり、そこに何か拡張機能を入れた覚えはありません。とりあえず、指示に従い、Visual Studio 2010(devenv.exe)を /log オプション付きで実行しました。

すると、上記ファイルに次のようなメッセージが出力されていました。

201906_vs2010_err2.png

Type: ERROR
Description: System.InvalidCastException: 型 'System.__ComObject' の COM オブジェクトをインターフェイス型 'Microsoft.VisualStudio.TextManager.Interop.IVsTextReplaceEvents' にキャストできません。IID '{CF9928D9-65AE-4319-A446-94ED5C45ECDE}' が指定されたインターフェイスの COM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました: インターフェイスがサポートされていません (HRESULT からの例外:0x80004002 (E_NOINTERFACE))。 場所 System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease) 場所 Microsoft.VisualStudio.TextManager.Interop.IVsTextReplaceEvents.OnReplace(ChangeInput[] pCI) 場所 Microsoft.VisualStudio.Editor.Implementation.VsTextBufferAdapter.OnTextBufferChangedHighPriority(Object sender, TextContentChangedEventArgs e) 場所 Microsoft.VisualStudio.Text.Utilities.GuardedOperations.RaiseEvent[TArgs](Object sender, EventHandler`1 eventHandlers, TArgs args)
Source: Editor or Editor Extension

Type: ERROR
Description: System.InvalidCastException: 型 'System.__ComObject' の COM オブジェクトをインターフェイス型 'Microsoft.VisualStudio.Editor.Implementation.IVsTextStreamEvents_Private' にキャストできません。IID '{96FC7D44-BCDD-4F00-AE4D-07E26B2C0E52}' が指定されたインターフェイスの COM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました: インターフェイスがサポートされていません (HRESULT からの例外:0x80004002 (E_NOINTERFACE))。 場所 System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease) 場所 Microsoft.VisualStudio.Editor.Implementation.IVsTextStreamEvents_Private.OnChangeStreamText(Int32 iPos, Int32 iOldLen, Int32 iNewLen, Int32 fLast) 場所 Microsoft.VisualStudio.Editor.Implementation.VsTextBufferAdapter.OnTextBufferChanged(Object sender, TextContentChangedEventArgs e) 場所 Microsoft.VisualStudio.Text.Utilities.GuardedOperations.RaiseEvent[TArgs](Object sender, EventHandler`1 eventHandlers, TArgs args)
Source: Editor or Editor Extension


エラーメッセージから何をどうしたらよいのかはさっぱり読み取れませんが、エラーメッセージの先頭の方の文字列をそのまま入れてググってみると解決策が見つかります。

201906_vs2010_err3.png

どうやら、64bit版Windowsの場合は、レジストリ エディタで「HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{73B7DC00-F498-4ABD-AB79-D07AFD52F395}\InProcServer32」を開き、既定の値に「C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\TextMgrP.dll」と入れてやればよいらしい。

ちなみに、32bit版Windowsの場合は、レジストリ エディタで「HKEY_CLASSES_ROOT\CLSID\{73B7DC00-F498-4ABD-AB79-D07AFD52F395}\InProcServer32」を開き、既定の値に「C:\Program Files\Common Files\Microsoft Shared\MSEnv\TextMgrP.dll」を入れてやります。

すると、無事にエラーが出なくなり、IntelliSenseも効くようになりました。

まさか、2019年にもなって、Visual Studio 2010のエラーに悩まされることになるとは…。


posted by ayacy at 00:00 | Comment(0) | TrackBack(0) | プログラミング