C#Excel - 不通过interop - macros和Solver参与发布

时间:2012-08-24 15:47:33

标签: c# excel interop excel-2010 excel-interop

啊,另一个“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()来电)。

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

1 个答案:

答案 0 :(得分: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;
}