0

I'm using the Excel interop for C# and all the methods to dispose of it exactly as described in many different places and no matter which method I use to dispose of the objects there is still an Excel.exe process running after the method finishes and everything should be finished and released. The existence of the process wouldn't bother me so much except you cannot open Excel without first closing my app which happens to terminate the Excel process at the same time.

Without resorting to actually figuring out which Excel processes have a parent process of my process and terminating them, I don't know what else to do.

Here is the current test method I'm using which should by all means work and releae:

    private bool FillExcelFileWithDataTest()
    {

        string sPath = "C:\\Some.xls";

        Excel.Application xlApp;
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        Excel.Range oRange = null;
        object misValue = System.Reflection.Missing.Value;

        xlApp = new Excel.Application();
        var xlWorkbooks = xlApp.Workbooks;
        xlWorkBook = xlWorkbooks.Open(sPath);
        var xlWorksheets = xlWorkBook.Worksheets;
        xlWorkSheet = xlWorksheets.get_Item(1);

        oRange = xlWorkSheet.Cells[1, 1];
        oRange.Value = "Test";

        oRange = xlWorkSheet.Cells[1, 1];
        oRange.Copy();
        oRange = xlWorkSheet.Cells[2, 1];
        oRange.PasteSpecial(Excel.XlPasteType.xlPasteFormats);

        if (oRange != null)
        {
            releaseObject(oRange);
        }

        releaseObject(xlWorkSheet);
        releaseObject(xlWorksheets);
        xlWorkBook.Save();
        xlWorkBook.Close(true, misValue, misValue);
        releaseObject(xlWorkBook);
        releaseObject(xlWorkbooks);
        xlApp.Quit();


        releaseObject(xlWorkSheet);
        releaseObject(xlWorksheets);
        releaseObject(xlWorkBook);
        releaseObject(xlWorkbooks);
        releaseObject(xlApp);

        GC.Collect();
        GC.WaitForPendingFinalizers();

        xlWorkSheet = null;
        xlWorksheets = null;
        xlWorkBook = null;
        xlWorkbooks = null;
        xlApp = null;
        return true;
    }

    private void releaseObject(object obj)
    {
        try
        {
            // Do not catch an exception from this.
            // You may want to remove these guards depending on
            // what you think the semantics should be.
            if (obj != null)
            {
                while(Marshal.FinalReleaseComObject(obj) > 0)
                { }
            }
            // Since passed "by ref" this assingment will be useful
            // (It was not useful in the original, and neither was the
            //  GC.Collect.)
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            MessageBox.Show("Exception Occured while releasing object " + ex.ToString());
        }
        finally
        {
            //GC.Collect();
        }
    }

What am I doing wrong?

Jay Croghan
  • 445
  • 3
  • 16
  • You don't [understand how the garbage collector works](http://stackoverflow.com/a/17131389/17034). Delete **all** the releaseObject() calls, they are useless. And move the GC.Collect() call into the caller of this method. – Hans Passant Jul 08 '16 at 21:22
  • @HansPassant Nope made no difference... – Jay Croghan Jul 08 '16 at 21:37
  • @HansPassant That worked perfectly. The link you first mentioned did not explain that in the least. Would you like to add your edited comment as an answer so I can mark it as such for future reference? Really, every other question and answer about this explained to do what I posted. Thanks. – Jay Croghan Jul 08 '16 at 22:04
  • Hmya, it does explain it perfectly and I don't care to water it down. That C# programmers don't understand garbage collection is a broad problem that I can only fix by posting detailed and accurate answers, water never taught anybody anything. – Hans Passant Jul 08 '16 at 22:12
  • I am not a "C# Programmer" so rid that of your opinion. From EVERYTHING I read, including official Microsoft documentation, it was imperative, regardless of the fact it is completely against how garbage collection in .Net works, to dispose of interop com objects individually and most even went to the lengths of explaining how every single reference object, oRange in my example above for instance, needed to be individually disposed of explicitly. The finger of blame for this lays solely on the information made most available when searching this exact problem and I'm not sure how that came to be – Jay Croghan Jul 08 '16 at 22:22
  • Well, now you know better. You're welcome. – Hans Passant Jul 08 '16 at 22:23
  • Thank you sincerely for the direct answer. What I would like to come from this is instead of marking this as a duplicate of a question which does not list in the results for questions relating to this exact issue that we can fix it somehow it does indeed list. – Jay Croghan Jul 08 '16 at 22:27

0 Answers0