未释放 Excel 互操作对象

本文关键字:对象 互操作 Excel 释放 | 更新日期: 2023-09-27 17:55:44

我正在使用以下方法。执行此代码块后,我通过检查任务管理器发现Microsoft Excel仍在后台运行。

编辑:只有一个Microsoft Excel后台进程保持活动状态。我只是添加这个,因为当我第一次开始使用 Excel 和互操作 COM 对象时,有时许多进程会在函数完成执行后保持运行。

如何确保在执行当前函数后 Excel 不会在后台运行?


我用全局范围声明这些变量,因为有几个函数最终需要它们:

private Excel.Application xls = null;
private Excel.Workbooks workBooks = null;
private Excel.Workbook workBook = null;
private Excel.Sheets sheets = null;
private Excel.Worksheet workSheet = null;

此方法用于检查给定工作簿中是否存在工作表:

private bool sheetExists(string searchString)
{
    xls = new Excel.Application();
    workBooks = xls.Workbooks;
    workBook = workBooks.Open(workbookPath); // <- Where the workbook is saved
    sheets = workBook.Sheets;
    bool isFound = false;
    foreach (Excel.Worksheet sheet in sheets)
    {
        // Check the name of the current sheet
        if (sheet.Name == searchString)
        {
            Marshal.ReleaseComObject(sheet);
            isFound = true;
            break;
        }
        Marshal.ReleaseComObject(sheet);
    }
    cleanUp(true, xls, workBooks, workBook, sheets);
    return isFound;
}

此函数用于释放 COM 对象:

private void cleanUp(bool saveTrueFalse, params object[] comObjects)
{
    workBook.Close(saveTrueFalse);
    xls.Application.Quit();
    xls.Quit();
    foreach (object o in comObjects)
    {
        Marshal.ReleaseComObject(o);
    }
    workSheet = null;
    sheets = null;
    workBook = null;
    workBooks = null;
    xls = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

未释放 Excel 互操作对象

我希望看到一个合适的解决方案,但这个黑客是我让它工作的唯一方法。似乎互操作库根本不擅长在被告知时关闭进程。如果在线程中运行,则会为每个线程启动进程。我会在启动后通过按名称扫描进程并跟踪新进程来跟踪进程 ID。我在服务器上执行此操作,因此我知道所有进程都是互操作启动的,而不是由实际用户启动的。在我完成逻辑后,我会启动一个计时器,每隔一分钟左右就会尝试终止该过程。最终它会关闭它。我还有一些代码可以在启动时杀死任何 Excel 进程,以防它们在上次应用程序运行时未正确终止。

如果您需要按名称或 id 杀死进程的示例代码,请告诉我。我没有现成的,或者快速的SO搜索应该会带来一些好的样本。