COM解放処理 | C#でExcelを読み込んで操作する方法を公開|C# Excel操作テクニック.NET

メソッドに貼り付けるだけで機能するソースコードを多数用意しています。

COM解放処理

COMプロセスが残る現象を防ぐためのクラス作成

このページで紹介するのは、単純に1つのExcelファイルを編集するときに、私がいつも使っているクラスの構成ルールです。

以下のルールに従って作成すれば、「COMの解放ができずにタスクマネージャにプロセスが残ってしまう。」という現象を軽減させることができるはずです。



1.クラスの構成

まず、Excelファイルの操作クラスを作成するときは、「クラスの作成」ページで公開しているように、クラス変数でWorksheetオブジェクトまでを宣言します。


2.メソッド・プロパティのルール

メソッドやプロパティを定義し、必要に応じてRangeやCellsを作って処理を作成します。

基本的にメソッド内で定義するオブジェクトはSheet以下のCellsやRangeのみとし、同じメソッド内で確実に解放します。


3.COM解放メソッド

これは私の中でいつも使っている手法ですので、上の2つとは少し違いますが・・・。

私がExcel操作クラスを作成するときに、いつも作成しているCOMオブジェクト解放用のメソッドです。


「2.メソッド・プロパティのルール」に書いた通り、メソッドやプロパティ内はCellsやRangeをメインで操作しますが、

シート切り替えやファイルを閉じるときなどの処理では、WorkSheetより上位のオブジェクトを操作することがあります。


例えばWorkBookを閉じる処理であれば、

WorkSheet → Sheets → WorkBook → WorkBooks

の順でオブジェクトを解放し、WorkBookを開くときは逆の順番でインスタンスを生成してあげる必要があります。


そこで私は、以下のようなEnumとメソッドを用意して、解放処理を1行で済ませられるように作成しています。

<Enum>
クラス変数で定義したオブジェクトに対応させて宣言しておきます。


        /// <summary>
        /// リリース対象
        /// </summary>
        private enum EnumReleaseMode
        {
            Sheet,
            Sheets,
            Book,
            Books,
            App
        }

<メソッド>
定義したEnumを引数に設定し、呼び出し側では「どこまで解放すればいいか」を指定できるようにしておきます。


        /// <summary>
        /// Excelリソース解放
        /// </summary>
        /// <param name="ReleaseMode">リリース対象Enum</param>
        private void ReleaseExcelComObject(EnumReleaseMode ReleaseMode)
        {
            try
            {
                // xlSheet解放
                if (xlSheet != null)
                {
                    Marshal.ReleaseComObject(xlSheet);
                    xlSheet = null;
                }
                if (ReleaseMode == EnumReleaseMode.Sheet)
                    return;

                // xlSheets解放
                if (xlSheets != null)
                {
                    Marshal.ReleaseComObject(xlSheets);
                    xlSheets = null;
                }
                if (ReleaseMode == EnumReleaseMode.Sheets)
                    return;

                // xlBook解放
                if (xlBook != null)
                {
                    try
                    {
                        xlBook.Close();
                    }
                    finally
                    {
                        Marshal.ReleaseComObject(xlBook);
                        xlBook = null;
                    }
                }
                if (ReleaseMode == EnumReleaseMode.Book)
                    return;

                // xlBooks解放
                if (xlBooks != null)
                {
                    Marshal.ReleaseComObject(xlBooks);
                    xlBooks = null;
                }
                if (ReleaseMode == EnumReleaseMode.Books)
                    return;

                // xlApp解放
                if (xlApp != null)
                {
                    try
                    {
                        // アラートを戻して終了
                        xlApp.DisplayAlerts = true;
                        xlApp.Quit();
                    }
                    finally
                    {
                        Marshal.ReleaseComObject(xlApp);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }