0

啊,SO上的另一个“Excel未发布”帖子.....

我有一个 Excel 工作簿,我通过 Excel (2010) 加载,调用 Excel 应用程序的 Run 方法在工作簿中启动宏,保存更新的工作簿并退出 Excel。

即使在调用应用程序关闭后,Excel 也会保持不变。

我还没有落入“两个点”的陷阱,我关闭所有可以关闭的,退出所有可以退出的并释放对每个使用的 COM 对象的引用并给 GC 一个踢。

如果我不调用运行宏,一切都很好。所以关于这个特定宏的某些东西是有问题的,因为其他工作簿没有显示这种行为。

宏本身加载 Solver 加载项并对非 .NET win32 dll 中的 C++ 函数进行一些调用。它调用 Solver 加载项,并没有做任何不寻常的事情(数学、设置范围、设置单元格值等)。

我应该知道任何与求解器或宏相关的问题吗?我什至尝试从 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()呼叫被删除)。

然而,这打破了“两个点”的规则。那么,它在做什么意味着我们可以在这种情况下侥幸逃脱,但在一般情况下却不行?

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 回答