简体   繁体   English

Excel Interop对象未被释放

[英]Excel Interop Objects not being released

I am using the below methods. 我使用以下方法。 After this code block executes, I find that Microsoft Excel is still running in the background via checking Task Manager. 执行此代码块后,我发现Microsoft Excel仍然通过检查任务管理器在后台运行。

Edit : Exactly one Microsoft Excel background process remains live. 编辑 :正好一个 Microsoft Excel后台进程仍然有效。 I am just adding this because when I first began working with Excel and Interop COM objects, sometimes many processes would stay running after the functions finished executing. 我只是添加这个,因为当我第一次开始使用Excel和Interop COM对象时,有时很多进程会在函数执行完毕后继续运行。

How do I ensure that Excel is not running in the background after my current function is executed? 执行当前函数后,如何确保Excel未在后台运行?


I declare these variables with global scope because several functions end up needing them: 我用全局范围声明这些变量,因为几个函数最终需要它们:

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;

This method is for checking if a sheet exists in a given workbook: 此方法用于检查给定工作簿中是否存在工作表:

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;
}

This function is for releasing the COM objects: 此函数用于释放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();
}

I'd like to see a proper solution but this hack was the only way I could get it to work. 我希望看到一个合适的解决方案,但这个黑客是我能够让它工作的唯一方法。 It seems that the interop library is not good at all at shutting the process down when told. 似乎互操作库在告诉时关闭过程并不是很好。 If running in threads, you'll get processes started for each thread. 如果在线程中运行,您将为每个线程启动进程。 I would keep track of the process id after one started by scanning processes by name and keeping track of new processes. 我会通过按名称扫描进程并跟踪新进程来跟踪进程ID。 I was doing this on a server so I knew all processes were interop started and not started by an actual user. 我在服务器上这样做,所以我知道所有进程都是互操作启动而不是由实际用户启动。 After I was done with the logic, I would start a timer that would try to kill the process every minute or so. 完成逻辑后,我会启动一个计时器,每隔一分钟就会尝试终止进程。 Eventually it would shut it down. 最终会把它关闭。 I also had some code that would kill any Excel processes on startup in case they weren't killed properly the last time the app was running. 我还有一些代码可以在启动时杀死任何Excel进程,以防上次应用程序运行时没有正确杀死它们。

Let me know if you want sample code for killing processes by name or id. 如果您想要按名称或ID杀死进程的示例代码,请告诉我们。 I don't have it readily available, or a quick SO search should bring some good samples. 我没有随时可用,或者快速SO搜索应该带来一些好的样本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM