Excel process remains open after interop; traditional method not working

青春壹個敷衍的年華 提交于 2019-11-30 19:16:05

This has worked successfully for me:

        xlApp.Quit();

        //release all memory - stop EXCEL.exe from hanging around.
        if (xlWorkBook != null) { Marshal.ReleaseComObject(xlWorkBook); } //release each workbook like this
        if (xlWorkSheet != null) { Marshal.ReleaseComObject(xlWorkSheet); } //release each worksheet like this
        if (xlApp != null) { Marshal.ReleaseComObject(xlApp); } //release the Excel application
        xlWorkBook = null; //set each memory reference to null.
        xlWorkSheet = null;
        xlApp = null;
        GC.Collect();

I am a total COM amateur, used it for a minor thing in one project quite a long time ago, but here's a snippet I used there. I probably found it somewhere online, don't remember. In any case, I paste it its full glory ;)

public static class ComBlackBox
{
    public static void ReleaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (ArgumentException ex)
        {
            obj = null;
            MessageBox.Show("Unable to release the Object " + ex.Message);
        }
        finally
        {
            GC.Collect();
        }
    } 
}

I'm unable to try it out now, but it probably worked (I honestly don't remember any details). Maybe it will help you out. Feel free to point out any obvious problems with this code, I really am far from being COM-literate ;)

This code works for me.

//Declare separate object variables
Excel.Application xlApp = new Excel.Application();
Excel.Workbooks xlWorkbooks = xlApp.Workbooks;
Excel.Workbook xlWorkbook = xlWorkbooks.Add(Missing.Value);
Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlWorkbook.Worksheets.get_Item(1);

//Create worksheet

xlWorkbook.Close(false, Missing.Value, Missing.Value);
xlWorkbooks.Close();
xlApp.Quit();

Marshal.FinalReleaseComObject(xlWorksheet);
Marshal.FinalReleaseComObject(xlWorkbook);
Marshal.FinalReleaseComObject(xlWorkbooks);
Marshal.FinalReleaseComObject(xlApp);

xlWorksheet = null;
xlWorkbook = null;
xlWorkbooks = null;
xlApp = null;

GC.Collect();

This article from Microsoft has some good information regarding this issue.

This is how I got around this problem:

// Store the Excel processes before opening.
Process[] processesBefore = Process.GetProcessesByName("excel");

// Open the file in Excel.
Application excelApplication = new Application();
Workbook excelWorkbook = excelApplication.Workbooks.Open(Filename);

// Get Excel processes after opening the file.
Process[] processesAfter = Process.GetProcessesByName("excel");

// Now find the process id that was created, and store it.
int processID = 0;
foreach (Process process in processesAfter)
{
    if (!processesBefore.Select(p => p.Id).Contains(process.Id))
    {
        processID = process.Id;
    }
}

// Do the Excel stuff

// Now close the file with the COM object.
excelWorkbook.Close();
excelApplication.Workbooks.Close();
excelApplication.Quit();

// And now kill the process.
if (processID != 0)
{
    Process process = Process.GetProcessById(processID);
    process.Kill();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!