0

My application launches and automates Excel:

Guid CLSID_ExcelApplication = ClsidFromProgID("Excel.Application");
Application xl = CoCreateInstance(CLSID_ExcelApplication);

And now we're off to the races:

Workbook wb = xl.Workbooks.Add();
Worksheet ws = wb.Worksheets[1];
ws.Name = "Monthly Expense Report";

And then normally you can .Quit Excel:

xl.Quit();

And Excel goes away.

Enter UserControl

What is supposed to happen is that if i had the code:

Application xl = CoCreateInstance(CLSID_ExcelApplication);
xl.UserControl = false;
Workbook wb = xl.Workbooks.Add();
Worksheet ws = wb.Worksheets[1];
ws.Name = "Monthly Expense Report";
ws = null;
wb = null;
xl = null;

Then Excel is supposed to automatically close when the last outstanding reference is gone. From MSDN:

Application.UserControl property (Excel)

When the UserControl property is False for an object, that object is released when the last programmatic reference to the object is released. If this property is False, Microsoft Excel quits when the last object in the session is released.

I'll just draw attention to that important line in the documentation above:

Microsoft Excel quits when the last object in the session is released

When .UserControl is false, Excel is supposed to automatically terminate.

The .UserControl property defaults to false. But even if i force it to false, the out-of-process Excel automation object does not quit when the last object in the session is released:

enter image description here

Crashing better

This becomes a problem if there is an unexpected exception while automating. Normally in order to get rid of Excel nicely you would:

  • Make it visible, and let the user close it:

    xl.Visible = true;
    xl.UserControl = true; //prevent Excel from terminating when we null our reference below
    xl = null
    
  • or call .Quit to quit:

    xl.Quit();
    xl = null;
    

Except if there is a catastrophic problem, i don't get a chance to call .Quit or call .Visible = true. And in these cases Excel is hanging around. Over days, weeks, and months it can sometimes mean literally dozen of them.

What can i do to ensure that Excel will close when the last outstanding reference to it is gone:

Application xl = CoCreateInstance(CLSID_ExcelApplication);
xl.UserControl = false;
Workbook wb = xl.Workbooks.Add();
Worksheet ws = wb.Worksheets[1];
ws.Name = "Monthly Expense Report";
ws.Cells[1,2] = "January";
ws.Ce......CRASH
Ian Boyd
  • 220,884
  • 228
  • 805
  • 1,125
  • What about using a little Autoit wrapper script? If your script fails then the outer Autoit script will close all excel.exe processes. – Xenobiologist Jul 03 '19 at 21:03
  • Instead of `UserControl`, can you try to set the `Visible` property to something, e.g: `xl.Visible = false` (or true if you need it visible). PS : the xl = null or xl = nothing are for most languages useless. – Simon Mourier Jul 03 '19 at 21:27
  • Have you tried `GetActiveObject` instead of opening an new instance each time? – Leandro Caniglia Jul 07 '19 at 01:51
  • [**GetActiveObject**](https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-getactiveobject) would consume an existing instance the user is using. I *need* a new instance. – Ian Boyd Jul 08 '19 at 14:28

0 Answers0