0

ああ、SO に関する別の「Excel がリリースされていない」投稿.....

Excel (2010) で読み込んだ Excel ワークブックがあり、Excel アプリケーションの Run メソッドを呼び出してブック内のマクロを起動し、更新されたワークブックを保存して Excel を終了します。

また、呼び出し元のアプリを閉じた後でも、Excel は遅れたままです。

私は「2つのドット」トラップに陥っていません。閉じることができるものをすべて閉じ、終了できるものをすべて終了し、使用されているすべてのCOMオブジェクトへのすべての参照を解放し、GCにキックを与えます。

マクロを実行するための呼び出しを行わなければ、すべて問題ありません。したがって、他のワークブックではこの動作が見られないため、この特定のマクロに何か問題があります。

マクロ自体が Solver アドインをロードし、.NET 以外の win32 dll で C++ 関数を呼び出します。ソルバー アドインを起動し、通常とは異なる処理 (数学、範囲の設定、セル値の設定など) は行いません。

知っておくべきソルバーまたはマクロ関連の落とし穴はありますか? 私は C# からアドインをアンロードしようとさえしました - 喜びはありません。

    static void NAR(object o) // MSDN article suggestion.
    {
        try
        {
            while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
            {
            }
        }
        catch
        {
            // swallow
        }
        finally
        {
            o = null;
        }
    }
    static void Excel(string FilePath, string SaveAsPath)
    {
        Application excelApplication = null;
        Workbooks workbooks = null;
        Workbook workbook = null;

        try
        {
            excelApplication = new Application { DisplayAlerts = false, Visible = false };
            workbooks = excelApplication.Workbooks;
            workbook = workbooks.Open(FilePath);

            excelApplication.Run("SolveEquationWithSolver");

            workbook.CheckCompatibility = false;
            workbook.SaveAs(SaveAsPath);
        }
        finally
        {
            if (workbook != null)
            {
                workbook.Close(Microsoft.Office.Interop.Excel.XlSaveAction.xlDoNotSaveChanges, Type.Missing, Type.Missing);
                NAR(workbook);
            }

            if (workbooks != null)
            {
                workbooks.Close();
                NAR(workbooks);
            }

            if (excelApplication != null)
            {
                excelApplication.Quit();
                NAR(excelApplication);
            }

            // Kick GC, as suggested elsewhere on SO. Not my idea.
            GC.Collect();
            GC.WaitForPendingFinalizers();

            // Double-tap GC, as suggested elsewhere on SO. Not my idea.
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

アップデート

別のフォーラムで の使用が提案されてexcelApplication.ActiveWindow.Close()おり、これは機能します!! (workbook.Close()コールが削除された場合)。

ただし、これは "2 つのドット" ルールに違反しています。では、このケースでは問題を回避できるが、一般的なケースではそうではないということは、何をしているのでしょうか?

4

1 に答える 1

1

私はある時点であなたと同様の問題を抱えていましたが、最終的にはあきらめて、Excel を強制終了することにしました。プロセスを強制終了する前に関連するワークブックを閉じると、迷惑な副作用 (次に Excel を開いたときにワークブックが "回復された" など) が発生することはありません。

using System.Runtime.InteropServices;

// ...
// Inside a class:

[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(
    IntPtr hWnd, out uint lpdwProcessId);

// Returns "true" on success, "false" on failure.
public static bool KillExcel(Application excel) {
    uint processId;
    GetWindowThreadProcessId((IntPtr)excel.Hwnd, out processID);
    try {
        Process.GetProcessById((int)processID).Kill()

    } catch (Exception /* TODO: catch only relevant exceptions */) {
        return false;
    }

    return true;
}
于 2012-08-24T15:59:18.993 に答える