VB.NETでAccessViolationException発生。DataGridViewが落ちる。



突然のAccessViolationException


VB.NETのWindowsアプリケーション画面で、不可解な現象が発生しました。

DataGridViewを使用しているFormを表示した後、他のアプリケーションをアクティブにしてしばらく経つと、裏でVB.NETのFormが落ちてしまうのです。

不思議なのは毎回発生するわけではなく、タイミングによって起きたり起きなかったりします。

イベントビューアでアプリケーションのログを見てみると、以下のようなエラーが記録されていました。

ハンドルされない例外のため、プロセスが中止されました。
例外情報:
System.AccessViolationException

デバッグ実行で確認しても、落ちたり落ちなかったりします。

落ちた場合の例外メッセージはイベントビューアに記録されているエラーと同じく、AccessViolationExceptionでした。

System.AccessViolationException はハンドルされませんでした。
保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。

AccessViolationException...

嫌な感じがします。

ドハマリして数日無駄にするパターン。

処理を見直しても怪しいところは無いし、なにより確実な再現が出来ないので困りました。

例外が発生する場合に共通している操作は、他のアプリケーションの裏にFormが移動した後に落ちるというところです。

ToolTipが関係している?

例外のStackTraceの中を見るとToolTipを経由している箇所がありました。

System.Windows.Forms.ToolTip.WndProc(Message& msg)
System.Windows.Forms.ToolTip.ToolTipNativeWindow.WndProc(Message& m)

ToolTip?
Google神にお伺いしてみたところ、以下のサイトをご教授頂きました。



再現手順:
  1. ツールチップが表示されるDataGridViewのセルの上にマウスを置く
  2. ツールチップが表示される前に素早くAltキー+Tabキーで他のアプリケーションを表示する
  3. しばらく待つ
  4. AccessViolationException発生
見事に再現しました。

とりあえず現象は分かったので良かった。

原因

どうやらComctl32.dllのバグらしいという情報がありました。

Microsoftサポートページ

ToolTipコントロールを表示する際に、内部的に使用されているComctl32.dllのバージョンが5.0だと例外が発生するそうです。

この問題はバージョン6.0で修正されているそうですが、バージョン6.0を選択するには「XP Visualスタイルを有効にする」という設定にしなければなりません。

実はこの現象が発生したシステムはVB6.0からアップグレードした資産で、VB6.0からアップグレードするとプロジェクトのプロパティの「アプリケーションフレームワークを有効にする」のチェックが外れます。

そのため、Visualスタイルが無効となり、Comctl32.dllはバージョン5.0が使用されていたようです。

この「アプリケーションフレームワークを有効にする」のチェックをオンに出来れば簡単なのですが、ボタンやグリッドの見た目が微妙に変わってしまうため、できればオンにしたくありません。

これ以外の解決方法はDataGridViewのShowCellToolTipsプロパティをFalseに設定するしかないのですが、ToolTipが出ないのはちょっと困ります。

解決方法

無理やりですが他に方法を思いつかなかったので、以下のような処理をFormに追加しました。

Private Sub Form_Activated(sender As Object, e As EventArgs) Handles Me.Activated
    Me.DataGridView1.ShowCellToolTips = True
End Sub

Private Sub Form_Deactivate(sender As Object, e As EventArgs) Handles Me.Deactivate
    Me.DataGridView1.ShowCellToolTips = False
End Sub

フォームがアクティブになったらActivatedイベントでDataGridViewのShowCellToolTipsプロパティをTrueに設定し、フォームが非アクティブになったらDeactivateイベントでDataGridViewのShowCellToolTipsプロパティをFalseに設定します。

これで画面が落ちることは無くなりました。

まとめ

VB6.0からVB.NETにマイグレーションしたシステムの場合は、上記の現象が当てはまるかもしれないので注意が必要です。(あまり無いと思いますけど)

以上

<スポンサーリンク>


0 件のコメント :

コメントを投稿