Preventing Excel.exe from hanging when using the Microsoft Excel Interop DLL with C#

So it’s been a bit quiet around here recently because I’ve been mostly working on a client project at the office which hasn’t included anything onerous that I felt a quick post would be useful to aid future development. Until now. Part of the work I’ve been completing has included working with Microsoft Excel through the use of the Excel Interop DLL. The DLL is fairly powerful and allows for a lot of interaction with Excel, but it isn’t without its problems, one of which is the issue of the Excel.exe process hanging on until your program closes.

The Excel.exe process is started when you begin the Excel app with the Interop DLL. If it hangs, it can prevent the file you had open from being accessible by other programs, or can cause other issues with Excel. Of course, if you made your Excel app visible, then you can just close the Excel program manually, but if you didn’t, then you have no way of forcing the process to terminate without killing it in the Task Manager, or closing your program to release the process. If your program wants to make use of that Excel file a second time (maybe a bit later on), it can fail if the original process is still hanging.

However, there is a solution, as this post will detail below.

COM Objects

The commonly accepted reason for the Excel.exe process to hang is the COM objects which are used in controlling and working with the Excel application aren’t properly cleaned up by the garbage collector. COM objects are special objects (and are also very annoying at times) which may require marshalling differently to normal objects.

Reminding the garbage collector to do its job

The garbage collector can be an occasionally lazy process in C# and sometimes you might need to remind it to do its job. So how can we force it to clean up COM objects? We can put the method using them in a try-finally structure, and calling upon the garbage collector in the ‘finally’ to clean up any remaining COM objects. What do I mean by this? Well, imagine you have a function that is working on an Excel file like this:

private void MyExcelFunction() //Pseudo code representation throughout
{
    var excelApp = Excel();
    var wb = excelApp.Workbook.Open(fileAddress);
    var ws = wb.ActiveSheet;
    ws.Cells[1, 1] = "Hello World!";

    //Etc. etc.
}

At the end of that function, we would normally expect the garbage collector to collect up all of the finished objects and dispose of them from memory as with any normal object. However, COM objects have a way of hanging on despite being out of scope, so we need to remind the garbage collector to clean them up. To do this, I wrapped ‘MyExcelFunction’ inside a try-finally loop, like the one below:

private void MyTryFinally()
{
    try
    {
        MyExcelFunction();
    }
    finally
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

private void MyExcelFunction() //Pseudo code representation throughout
{
    var excelApp = Excel();
    var wb = excelApp.Workbook.Open(fileAddress);
    var ws = wb.ActiveSheet;
    ws.Cells[1, 1] = "Hello World!";

    //Etc. etc.
}

By wrapping up the function in a try-finally structure, we can ensure that the garbage collector (‘GC’) will collect up any unused objects at the end of the code being executed in the ‘try’ statement. This has worked for cleaning up the Excel.exe process in my code and preventing the Excel.exe process from hanging.

However, if this doesn’t work for you, maybe you’d like to try this:

Don’t ‘double dot’ COM objects

There is an unofficial rule (which you can usually find on StackOverflow posts relating to COM object problems) that you shouldn’t ‘double dot’ COM object properties as it creates COM objects which you can’t dispose of yourself. An example of what I mean by ‘double dot’ is given below.

var wb = excelApp.Workbook.Open(fileAddress);

Notice the dot’s between ‘excelApp’ and ‘Workbook’ and ‘Workbook’ and ‘Open’? That’s ‘double dotting’, and its a common practice in coding when referring to properties found in sub-objects of your current object.

However, when working with COM objects, by using this method, a COM object for handling the ‘Workbook’ has been created but isn’t assigned to a variable that you can clean up afterwards. Therefore, the unofficial rule suggests that you should actually do something like this:

var workbook = excelApp.Workbook;
var wb = workbook.Open(fileAddress);

This removes the ‘double dot’ and gives you a variable with some control over its disposal and clean-up later on.

However – I have not found this to be an issue in my code. I am happily ‘double dotting’ all over the place and I don’t have Excel.exe hanging as a result of using the method above. I present this solution however because there are many people who have reported that ‘double dotting’ was the cause of their problem so, if you’ve tried the above method and you still have Excel.exe hanging, you may wish to try this alternative method. But for me, I’m happy with my ‘double dotting’ and will continue with it until such time it seems prudent not to.

So that’s all for this post, hopefully this prevents your Excel.exe process from hanging or prevents mine from hanging the next time I’m tasked with working with the Excel Interop DLL…

Leave a Reply

Your email address will not be published. Required fields are marked *