【问题标题】:Proper way of closing Excel application关闭Excel应用程序的正确方法
【发布时间】:2012-03-23 19:30:22
【问题描述】:

我正在编写一个应用程序,它使用以下代码访问 Excel 文件:

RBTApplication = new Excel.Application();
RBTWorkbooks = RBTApplication.Workbooks;
RBTWorkbook = RBTApplication.Workbooks.Open(
    RBTDataSet.Instance.FilePath, 0, true, 5, "", "", true,
    Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
    "\t", true, false, 0, true, 1, 0 );
RBTWorksheet = (Excel.Worksheet)RBTWorkbook.Worksheets.get_Item( 1 );
RBTRange = RBTWorksheet.UsedRange;

加载我需要的数据后,我尝试使用这段代码关闭 Excel 应用程序:

RBTWorkbook.Close();
RBTApplication.Quit();
RBTWorksheet.ReleaseComObject();
RBTWorkbook.ReleaseComObject();
RBTWorkbooks.ReleaseComObject();
RBTApplication.ReleaseComObject();

我的问题是 EXCEL.EXE 进程仍在运行。 像杀死所有 Excel 进程这样的简单解决方案听起来并不好,因为我的进程可能是同时使用的许多电子表格之一。这也会影响打开新的 excel 电子表格 - 每个都以只读方式打开,直到我不终止此进程。

那么...如何正确关闭此应用程序或终止此特定进程(有没有办法从 COM 对象获取 PID?)。我想我找到了一个(还没有尝试过) - 在打开新的 ExcellApp 之前和之后获取 Excell 进程列表,比较列表(获取差异),杀死知道其 PID 的特定进程。但这个解决方案似乎不是从我的应用程序中处理 COM 对象和其他应用程序的正确方法。

【问题讨论】:

    标签: c# com excel-interop


    【解决方案1】:

    您并未释放所有 COM 对象。

    例如:

    RBTApplication.Workbooks.Open
    

    将实例化一个Workbooks 对象,如下所示:

    RBTWorkbook.Worksheets.get_Item
    

    改为使用您已经创建的 Worksheets 对象:

    RBTWorkbooks = ...
    ...
    RBTWorkbooks.Open(...)
    RBTWorkbooks.get_Item(...)
    

    如果您的互操作要求很简单,并且互操作代码已本地化,您可以小心地确保释放您引用的所有 COM 对象,最好使用 try/finally 来确保即使抛出异常也释放它们.

    但是,您或维护程序员很容易忘记一个,因此您可能希望查看强制垃圾回收,例如 see the answers to this question.

    【讨论】:

    • 这首先是一个错误,我创建了 RBTWorkbooks 来释放这个对象,但也忘记更改进一步的代码,我发现了更多困扰我的事情 - 例如RBTRange.Rows.Count 的 Rows 对象是否也必须被释放?
    猜你喜欢
    • 2013-08-05
    • 1970-01-01
    • 2012-03-08
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多