徘徊Excel流程

时间:2018-05-31 15:54:17

标签: c# excel com office-interop

我正在做一个Windows服务,我正在使用Microsoft.Office.Interop.Excel来创建一个新的excel文件,编辑它并保存它。

完成它,关闭相应的对象(工作表,工作簿),退出excel应用程序,Marshal释放COM对象后,该过程仍然挥之不去。

    private void doWork()
    {
        var excelApp = new MsExcel.Application();
        var workBooks = excelApp.Workbooks;
        var workbook = excelApp.Workbooks.Add();
        var sheets = workbook.Sheets;
        _worksheet = workbook.Sheets[1];

        //Do Work Here

        _worksheet.SaveAs(filePath);
        workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
        workBooks.Close();
        releaseObject(_worksheet);
        releaseObject(sheets);
        releaseObject(workbook);
        releaseObject(workBooks);
        excelApp.Quit();
        releaseObject(excelApp);

    }

    private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            _log.Error($"Unable to release object {obj} Error:" + ex.ToString());
            obj = null;
        }
        finally
        {
            GC.Collect();
        }
    }

我看到其他一些帖子建议发布对象,以及对工作簿和表格的引用。不确定,为什么这仍然不起作用。

2 个答案:

答案 0 :(得分:0)

Microsoft目前不建议也不支持从任何无人参与的非交互式客户端应用程序或组件(包括ASP,ASP.NET,DCOM和NT服务)自动化Microsoft Office应用程序,因为Office可能会出现不稳定Office在此环境中运行时的行为和/或死锁。

如果要构建在服务器端上下文中运行的解决方案,则应尝试使用已为安全无人值守执行的组件。或者,您应该尝试找到允许至少部分代码在客户端运行的替代方法。如果从服务器端解决方案使用Office应用程序,则应用程序将缺少许多成功运行的必要功能。此外,您将承担整体解决方案稳定性的风险。请在Considerations for server-side Automation of Office文章中详细了解相关内容。

作为一种解决方法,您可以考虑使用One XML SDK或为服务器端或服务执行而设计的任何其他第三方组件。

答案 1 :(得分:0)

您不应该调用ReleaseComObject。这是一个很久以前开始的旧妻子故事,但it is incorrect

如果您看到excel实例,它可能意味着您的程序终止而不运行仍然保留在com对象中的垃圾收集器和引用。解决问题的最佳方法是完全摆脱释放功能,然后在GC.Collect()方法返回后调用doWork()

private void doWork()
{
    try
    {
        doWorkImpl();
    }
    finally
    {
        GC.Collect(); //The GC collect needs to be here, after the scope of doWorkImpl ends.
        GC.WaitForPendingFinalizers(); //The excel instance gets closedin the finalizer.
    }
}

private void doWorkImpl()
{
    var excelApp = new MsExcel.Application();
    var workBooks = excelApp.Workbooks;
    var workbook = excelApp.Workbooks.Add();
    var worksheet = workbook.Sheets[1]; //This needs to be a local variable, not a class variable.

    //Do Work Here

    worksheet.SaveAs(filePath);
    workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
    workBooks.Close();
    excelApp.Quit();

}

只要没有抛出异常并成功调用excelApp.Quit(),这就会导致excel实例继续运行。

但是,如果您只使用xlsx文件而不是xsl文件,我会 高度 建议远离com互操作,只需使用the SDK microsoft provides即可直接与.xlsx文件进行交互。