1

ここで提起された多くの同様の質問を認識しており、好奇心を満足させる解決策を見つけることなく、それらのほとんどを調べました(私のケースはもう少し具体的だと思います)。
WPF アプリケーション内の Excel ワークブックの名前付き範囲の名前からコレクションを作成しようとしています。その結果、アプリケーションを閉じた後でも Excel プロセスが実行されます。問題を次のコードにローカライズしました。それがなければ、すべて正常に動作します:

foreach (Excel.Name name in names)
{
      namedRanges.Add(name.Name);                            
}

したがって、明らかに、ここにあるものはリリースされません。他のExcelオブジェクトと同様に、「Excel.Name」を閉じる/破棄する/終了する方法が見つかりませんでした。その方法を提案してください。私が使用している回避策は、特定のプロセスを強制終了することですが、この背後にある問題を理解し、より適切な解決策を見つけようとしています。完全なコードの抜粋は次のとおりです。

     Excel.Application excel = new Excel.Application();
     excel.Visible = false;
     Excel.Workbooks wbooks = excel.Workbooks;
     Excel.Workbook wbook = wbooks.Open(Proc.ExpenseFullPath);

     ObservableCollection<string> namedRanges = new ObservableCollection<string>();
     Excel.Names names = wbook.Names;

     foreach (Excel.Name name in names)
     {
          namedRanges.Add(name.Name);                            
     }                        

     wbook.Close();
     wbooks.Close();
     excel.Quit();

編集:それを機能させる方法を見つけました。問題のある「foreach」を次のように置き換えました。

for (int i = 1; i <= names.Count; i++)
{
     namedRanges.Add(names.Item(i).Name);
     Marshal.FinalReleaseComObject(names.Item(i));
}
4

3 に答える 3

1

これは、あなたのような状況で com オブジェクトが適切に解放されないことに関する優れた投稿です。

  1. プロジェクトのビルド モードを「リリース」に変更しました (DEBUG モードでは、COM オブジェクトは参照を破棄するのに苦労します。
  2. すべてのダブル ドット式を削除しました (すべての COM オブジェクトを変数に関連付けて、解放できるようにする必要があります)。
  3. GC.Collect()、GC.WaitForPendingFinalizers()、および Marshal.FinalReleaseComObject() を finally ブロックで明示的に呼び出す

これを試してみてください:

Marshal.ReleaseComObject(names);

申し訳ありませんが、まだ十分な評判が得られていないため、これをコメントとして残すことができます.

于 2013-11-02T14:09:56.117 に答える
0

これを追加:

Marshal.ReleaseComObject(wbook);
Marshal.ReleaseComObject(excel);
于 2013-11-02T14:08:39.040 に答える
0

私は数年前に同様の問題に遭遇し、それと戦うためにいくつかのテクニックを使用しました. 私たちの使用例はあなたのものとは少し異なるかもしれません - 私たちは複数の Excel インスタンスを生成してそれらを閉じる (しようとする) 作業を行う長時間実行サービスを持っていました。

ここhttp://www.xtremevbtalk.com/showpost.php?p=1335552&postcount=22からWin32ジョブAPIについて知り、コードをそのままコピーしました。Excel インスタンスをホスト アプリケーションの PID に登録し、アプリケーションが停止すると Excel も停止します。ホストがクラッシュしても、次のように使用します。

uint pid = 0;
GetWindowThreadProcessId(new IntPtr(_excel.Hwnd), out pid);
_job = new Job();
_job.AddProcess(Process.GetProcessById((int) pid).Handle);

次に、Excel によって割り当てられたものに対して "NAR" という関数を実行します。

private static void NAR(object o)
{
    if (o == null) return;
    try
    {
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o);                
    }
    catch { }
    finally
    {
        o = null;
    }
 }

そして最後に、閉鎖するときに実行したいガベージ コレクションの呪文があります。

private static void GcCleanup()
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
}

なぜそれが2回行われたのか思い出せませんが、理由があったことは覚えています。これらの手法のいずれかが Excel を使いこなすための優れた/正しい方法であると断言することはできませんが、私にとってはうまくいきました!

于 2013-11-02T14:27:48.447 に答える