.NETでPDFを開くときの注意

PDFを.NETアプリケーションで開くには、大きく分けて2つの方法がある。

  1. WebBrowserコントロールを利用する
  2. Adobe社のActiveXコンポーネントを直接利用する(Adobeじゃなくても良いが)


ところが、どちらの場合もアプリケーション終了後にトラブルが起きる。
メモリアクセス違反であったり、PDFビューアのプロセスがゾンビになってしまったり。*1



この問題は多くの人が悩んだらしく、Webに情報が大量に落ちている。


これらを総合すると、対策はDisposeに実装するのが良いようだ。
ActiveXコンポーネントの破棄にはOLE32.dllのCoFreeUnusedLibrariesを利用する。
参考:方法 : Dispose Finalize パターンを実装する (Visual Basic)
WindowsFormの場合は以下のような実装になる。
WebBrowserコントロールを使用した場合に「空白ページ(about:blank)に遷移させる」という情報もあったのだが、
自分の環境(.NET Framework3.5 + AdobeReader8)では無意味であった。下記対応で回避できている。*2

  Declare Sub CoFreeUnusedLibraries Lib "ole32.dll" ()

  'フォームがコンポーネントの一覧をクリーンアップするために dispose をオーバーライドします。
  <System.Diagnostics.DebuggerNonUserCode()> _
  Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
      If disposing AndAlso components IsNot Nothing Then
        components.Dispose()
      End If

      ' 自動生成されているDisposeメソッドに次の2行を追加
      Application.DoEvents()   ' これ大事。OSに制御を渡してイベントを処理させる。
      CoFreeUnusedLibraries()  ' Adobe Readerのごみメモリを解放する。

    Finally
      MyBase.Dispose(disposing)
    End Try
  End Sub

*1:AdobeReader8までは「AcroRd32.exe」がゾンビになっていたが、AdobeReader9は違う仕組みで表示しているのかAcroRd32は起動しない。詳細は調査していないので不明。

*2:AcroRd32.exeが終了するまで若干時間がかかるようだが。