简体   繁体   中英

Excel 2010 com object references not released

The following code sample worked just fine in Excel 2007, but when I installed Excel 2010 (32bit) it would leave the excel.exe process open unless I added the GC.Collect(). My simple question is am I doing something wrong? It looks like to me like I am releasing everything I use.

    public override void Update()
    {

        StatusBox.AddStatus("Opening File " + ImportPath);

        Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
        Microsoft.Office.Interop.Excel.Workbook wb = app.Workbooks.Open(ImportPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets[1];

        Range rng = ws.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);

        int LastRow = rng.Row;

        StatusBox.AddStatus(LastRow.ToString() + " Rows Found in File");


        StatusBox.AddStatus("Closing File " + ImportPath);

        System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
        rng = null;

        System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
        ws = null;

        wb.Close(true, ImportPath, null);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
        wb = null;

        GC.Collect();

        app.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
        app = null;
    }

You need to call both GC.Collect / GC.WaitForPendingFinalizers and Marshall.FinalReleaseComObject.

See my answer here for details:

How do I properly clean up Excel interop objects?

Note that the advice (and apparently the more popular answer) to "never use two dots" in any given command is valid, but virtually impossible to enforce in practice. If you make any mistake anywhere in your code, the Excel application will hang and there is no profiling tool on the planet that can help you -- you'd have to review all your code by eye. For a large code base, this is essentially impossible.

In your code, you do not have a call to GC.WaitForPendingFinalizers after your call to GC.Collect. This is necessary to ensure that your garbage collection calls are synchronous. (GC.Collect operates on a different thread, if you don't wait for it, the collection could occur out of order with respect to your subseqent object releases and you want to release minor COM objects, like Ranges, first, and the major COM objects like Workbooks and the Application, last.) After calling GC.Collect and GC.WaitForPendingFinalizers, you would then want to call Marshall.FinalReleaseComObject on your named references.

So, in short, the strategy is to call GC.Collect and GC.WaitForPendingFinalizers to release the COM objects to which you do not hold a reference and call Marshall.FinalReleaseComObject to release the COM objects to which you do hold a named reference.

-- Mike

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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