0

I need to create report in xlsx format. After the report has been created and file saved I am releasing resources but process is not disappearing from Task Manager. Here is my method.

            excelApplication = new Excel.Application();
            wBooks = excelApplication.Workbooks;
            wBook = wBooks.Add(Excel.XlSheetType.xlWorksheet);
            sheet = (Excel.Worksheet)excelApplication.ActiveSheet;

            for (int j = 0; j < outDistribution.Count; j++)
            {
                var sh = (Excel.Range)sheet.Cells[j + 1];
                sh.Value2 = outDistribution[j];
                Marshal.ReleaseComObject(sh);
            }

            SaveFile(wBook);
        }
        catch (Exception ex)
        {

        }
        finally
        {
            Helper.ReleaseCOMObject(sheet);
            Helper.ReleaseCOMObject(wBook);
            Helper.ReleaseCOMObject(wBooks);
            Helper.ReleaseCOMObject(excelApplication);
        }

ReleaseCOMObject method:

public void ReleaseCOMObject(object obj)
    {            
        if (obj is Excel.Worksheet)
        {
            Marshal.FinalReleaseComObject(((Excel.Worksheet)obj).Cells);
            Marshal.ReleaseComObject(obj);
            obj = null;
        }

        if (obj is Excel.Workbook)
        {
            ((Excel.Workbook)obj).Close(false);
            Marshal.ReleaseComObject(obj);
            obj = null;
        }

        if (obj is Excel.Workbooks)
        {
            ((Excel.Workbooks)obj).Close();
            Marshal.ReleaseComObject(obj);
            obj = null;
        }

        if (obj is Excel.Application)
        {
            ((Excel.Application)obj).Quit();
            Marshal.ReleaseComObject(obj);
            obj = null;
        }
    }

I have rad a lot of posts on this resource and others but nothing work for me.

mojo
  • 174
  • 1
  • 2
  • 9
  • You'd better try "using" operator instead of manual release. – Leonid Malyshev Oct 24 '16 at 10:42
  • 1
    You must still have a reference to a COM object somewhere, although to be fair to you I can't spot it in your code. You could try adding `GC.Collect(); GC.WaitForPendingFinalizers();` as the first line in your `ReleaseCOMObject` method. [This post](http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects/) is the best one I've found on the subject. – Equalsk Oct 24 '16 at 10:46
  • Yes I think the COM objects creating during this piece of code: for (int j = 0; j < outDistribution.Count; j++) { var sh = (Excel.Range)sheet.Cells[j + 1]; sh.Value2 = outDistribution[j]; Marshal.ReleaseComObject(sh); } but I do not understand where – mojo Oct 24 '16 at 11:00
  • 1
    Also according to the first message I can not use "using" statement. This is only for object which implement IDisposable interface. – mojo Oct 24 '16 at 11:07
  • 1
    Yes, you missed one. That it is so completely undebuggable is the basic reason you should **never** write code like this. You can stare at the code for days and you'll never see it. sheet.Cells[j + 1] has *two* object references, one for the Cells object, another for the Range object. You did not release Cells. Also no obvious place where you call Quit() btw. Remove all the horrid Helper.ReleaseCOMObject() calls from this code, they didn't help a bit. Call GC.Collect() in the *caller* of this method, the GC never gets this wrong. – Hans Passant Oct 24 '16 at 12:09
  • It helps for me. Thanks, Hans. You have mentioned that "you should never write code like this". You mean the for loop or ReleaseCOMObject() method or whole code? And maybe you can give me some advice or resource for best practice. Thanks. – mojo Oct 24 '16 at 12:45

0 Answers0