Office オートメーションで割り当てたオブジェクトを解放する – Part2

こんにちは、Office 開発系サポート 森 健吾 (kenmori) です。 今回の投稿では、Office オートメーションの実装コードで割り当てたオブジェクトを解放する – Part1 の続編を記載いたします。続編では、前回の投稿でベスト プラクティスとして紹介した解放処理に対して解説を実施した後、正しくオブジェクト解放を実施しない場合に生じる影響についてご紹介します。 最初に、オブジェクト解放漏れがあると、主に以下のような事象があるということは先に述べておきます。 ・意図とは異なる COM オブジェクトに接続され、想定とは異なる結果を返し、アプリケーションの動作に予期せぬ影響を与えます。・通常のメソッド実行にも関わらず COMException 等の例外が返さることがあります。・イベント呼び出し時にフリーズすることがあります。・Office の内部処理 (例. 終了時の処理など) に予期せぬ影響を及ぼすことがあります。・解放漏れのオブジェクトがメモリを圧迫します。  オブジェクトの解放漏れと聞いて、誰もが最初に思いつくメモリ圧迫などのパフォーマンスへの影響以外にも実に様々な問題の要因となります。今回は、この投稿を読み終えた後、なぜそうなるかが理解できるようになることを目標とします。なお、幅広い読者層を想定して、可能な限りわかりやすい記述を心掛けます。そのため、なるべく簡略化した説明にするためにより一般的な内容だけにフォーカスし、細かな説明等は省いております。フィードバック等がありましたらお知らせください。 まずは、Part 1 で確認したベスト プラクティスのコードを分析しましょう。   1.    ベスト プラクティスのコードを分析する   1)     .NET における Interop COM オブジェクトの生成について New 演算子で Excel.Application クラス等を生成すると、RCW (ランタイム呼び出し可能ラッパー) も生成され COM オブジェクトのインスタンスを管理することになります。 注意点としては、RCW は COM オブジェクトとは別の形で参照カウントをカウントしている点になります。そのため、既存のアンマネージ COM オブジェクトに対して接続する際においては、独自の参照カウンタのみを増やし、既存オブジェクトを再利用する動作等に至ります。 タイトル : ランタイム呼び出し可能ラッパーアドレス :…


1. Office PIA 経由で Office 製品をオートメーションすることによる、Office オブジェクトモデルの操作

こんにちは、Office 開発系サポートの柴田 茂 (sshibata) です。本稿で表現している、Office オートメーションとは、Windows 上の全く別のアプリケーションを使用して、Office によって通常は手動やマクロによって行われる処理を、自動化する仕組みとなります。例えば、Excel のオートメーションを使用すれば、新規ブックの作成、ブックへのデータ入力、グラフの作成などの作業を自動的に実行させることができます。Excel などの Microsoft Office アプリケーションでは、通常はユーザー インターフェイスを介して手動で実行する機能のほぼすべてを、オートメーションによってプログラムから実行することができます。 Microsoft Office では、プライマリ相互運用機能アセンブリ (PIA) と呼ばれるライブラリが用意されており(以下Office PIA)、これを使用することで、Office アプリケーションによって公開されている COM オブジェクトを使ってOfficeを外部から操作するOffice ソリューションを開発することができます。 利用できるオブジェクトやメソッドの名前はほぼVBA と一緒であり、従来VBA マクロに限定されていたOffice 用のオブジェクトが、外部アプリケーションからアクセスできるインターフェースとして公開されているということになります。 このテクノロジを実装した場合の実行条件は、クライアント環境に、操作対象の Officeアプリケーションがインストールされていて、かつ対象バージョン以降の.NET Framework がインストールされていることと、Office PIA がGAC(グローバルアセンブリキャッシュ) に登録されていることになりますが、詳細については、次回以降に掘り下げたいと思います。 さて、Visual Studio にてアプリケーションを作成し、参照設定から、Office のタイプライブラリ経由で Office 製品のインスタンスを生成してコーディングを始めると、インテリセンス等でも確認できる通り、必要なオブジェクトを取得すれば、VBA と同じ感覚でプログラミングすることができます。 基本的には、Office アプリケーション上で、ユーザー インターフェイスを介して手動で実行する機能のほぼすべてを、実装することができます。 注意点としては、先日の森さんの投稿(Office オートメーションで割り当てたオブジェクトを解放する – Part1) のようなCOM オブジェクトを操作しているという意識を持って、オブジェクトを明示的に破棄するなどの処理を行ったり、イベントを適切に扱う等の考慮事項が発生します。さて、実際にOffice アプリケーションのイベントを扱うサンプルをご紹介しましょう。 今回制御したいのは、Excel ワークブックが閉じる直前に発生するWorkbookBeforeCloseイベントです。 AppEvents_Event.WorkbookBeforeClose イベントhttp://msdn.microsoft.com/ja-jp/library/microsoft.office.interop.excel.appevents_event.workbookbeforeclose(office.11).aspx VB.NET の場合には、WithEvents を使って変数を定義すると、VBA のイベント共有と同じように、WithEvents…


Office のプロセス インスタンス制御について

こんにちは、Office 開発系サポート 森 健吾 (kenmori) です。 今回の投稿では、Office のプロセス インスタンス制御というテーマにて記載いたします。 Office アプリケーションは MDI (Multi Document Interface) アプリケーションとして開発されており、1 つのプロセスで複数のドキュメントを扱えるように実装されています。 様々な場合において、既存のプロセス インスタンスでドキュメントを開くか、新しいプロセスを起動してドキュメントを開くかを制御しています。 この動作は、Office の自動化プログラムを実装するにあたり、色々と影響があるため、事前に把握しておいた方が良い内容と思い、ご紹介させていただくに至りました。   新規 / 既存プロセスで開く操作に関する一覧 No 操作 Word Excel PowerPoint 1 プログラムを起動する 既存 新規 既存 2 エクスプローラからファイルを開く 既存 既存 既存 3 オブジェクト生成 (CreateObject) 新規 新規 既存 4 OLE 埋め込みオブジェクト 既存 既存 既存 ・上記記載の通り、各 Office アプリケーションで動作が異なります。 ・“新規”…


Office オートメーションで割り当てたオブジェクトを解放する – Part1

こんにちは、Office 開発系サポート 森 健吾 (kenmori) です。 今回の投稿では、Office オートメーションの実装コードで割り当てたオブジェクトを解放するというテーマにて記載いたします。 .NET Framework 上で動作するカスタム アプリケーションにおいて、Office オートメーションで処理を実装する場合には割り当てたオブジェクトを確実に解放することをお勧めします。   2016/12/2 Update サンプル コードを中間オブジェクトも解放するよう、より適切な形に変更しました。   2017/3/28 Update アプリケーション終了前に一部のオブジェクトを解放するよう、サンプル コードをさらに適切な形に変更しました。   これは、Office が内部的に OLE や DDE などを通じて実施するオブジェクト インスタンス制御 (※) によって CLR 上で解放漏れ (または解放待ち) のオブジェクトが誤って参照されてしまい、カスタム アプリケーション側の動作に様々な予期せぬ影響を与えることにあります。 ※ OLE や DDE などを通じて実施するオブジェクト インスタンス制御や、解放漏れによる影響等については、別途記載を予定しております。 今回は、詳細な上記の詳細な理由や解放しない際の影響等は省略し、オブジェクト解放の正しい実装方法について記載します。   1.     割り当てたオブジェクトを解放する Office オートメーションで割り当てたオブジェクトについては、自分で解放処理を記載して必ず破棄される必要があります。 例えば、以下の Windows アプリケーションにおけるサンプル コードでは VB.NET で…