1

I am trying to work with Excel via COM interop. It works fine but Excel process is still hanging after DoStuff method is finished (though it disappears when my program finishes).

If I remove the code that fills cell I do not have this issue.

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;

namespace ConsoleApplication13
{
    class Program
    {
        static void DoStuff()
        {
            string workbookPath = @"C:\....xlsx";

            var excelApp = new Excel.Application();

            excelApp.Visible = true;

            var workbooks = excelApp.Workbooks;

            var workbook = workbooks.Open(workbookPath,
                0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
                true, false, 0, true, false, false);

            var workheets = workbook.Worksheets;

            var mainWorksheet = (Excel.Worksheet) workheets.Item[1];

            var cell = (Excel.Range)mainWorksheet.Cells[4, "U"];

            cell.set_Value(Missing.Value, 99);

            ReleaseObject(cell);

            ReleaseObject(mainWorksheet);
            ReleaseObject(workheets);

            workbook.Close(false, Missing.Value, Missing.Value);

            ReleaseObject(workbook);
            ReleaseObject(workbooks);

            excelApp.Quit();

            ReleaseObject(excelApp);

        }

        private static void ReleaseObject(object obj)
        {
            if (obj != null && Marshal.IsComObject(obj))
            {
                Marshal.ReleaseComObject(obj);
            }
        }

        static void Main(string[] args)
        {
            DoStuff();

            Console.ReadKey();
        }
    }
}

I am trying to store all references to COM objects and release it as was suggested here How do I properly clean up Excel interop objects? but it doesn't work for Cells and I don't understand why.

Community
  • 1
  • 1
Alex P.
  • 3,697
  • 9
  • 45
  • 110
  • Have you tried using `FinalReleaseComObject` instead of `ReleaseComObject`? – wertzui Feb 03 '16 at 12:09
  • Possible duplicate of [How to properly clean up Excel interop objects?](http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects) – Alex K. Feb 03 '16 at 12:10
  • The same with `FinalReleaseComObject`. – Alex P. Feb 03 '16 at 12:19
  • 1
    The Cells[4, "U"] expression creates an interface reference that you cannot see and can therefore not release. Writing manual memory management code like this is very, very unwise. Use the garbage collector, it never gets it wrong. Just make sure you [use it correctly](http://stackoverflow.com/a/25135685/17034). – Hans Passant Feb 03 '16 at 14:09

1 Answers1

0

I ended up doing something like this with the GC approach. Looks like it works fine.

using System;
using System.Reflection;
using Excel = Microsoft.Office.Interop.Excel;

namespace ConsoleApplication13
{
    class ExcelWorker : IDisposable
    {
        private Excel.Application _excelApp;

        private Excel.Workbook _workbook;
        private Excel.Worksheet _mainWorksheet;

        private readonly string _workbookPath;

        public ExcelWorker(string workbookPath)
        {
            _workbookPath = workbookPath;
        }

        public void Start()
        {
            _excelApp = new Excel.Application();

            _excelApp.Visible = true;

            var workbooks = _excelApp.Workbooks;

            _workbook = workbooks.Open(_workbookPath,
                0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
                true, false, 0, true, false, false);

            var workheets = _workbook.Worksheets;

            _mainWorksheet = (Excel.Worksheet) workheets.Item[1];
        }

        public void DoStuff()
        {
            var cell = (Excel.Range)_mainWorksheet.Cells[4, "U"];

            cell.set_Value(Missing.Value, 99);
        }

        public void Stop()
        {
            if (_workbook != null)
            {
                _workbook.Close(false, Missing.Value, Missing.Value);

                _workbook = null;
                _mainWorksheet = null;
            }

            if (_excelApp != null)
            {
                _excelApp.Quit();

                _excelApp = null;
            }

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

        public void Dispose()
        {
            Stop();
        }
    }

    class Program
    {

        static void Main(string[] args)
        {
            using (var excelWorker = new ExcelWorker(@"C:\.....xlsx"))
            {
                excelWorker.Start();

                excelWorker.DoStuff();

                excelWorker.DoStuff();
            }

            Console.ReadKey();
        }
    }
}
Alex P.
  • 3,697
  • 9
  • 45
  • 110