Aaron
Aaron

Reputation: 61

quitting excel with C# (while using excel automation)

I'm using c# to read/write data to an excel spreadsheet.

I'm using these three statements to open my excel file

 Excel.Application excelapp = new Excel.Application();
 Excel._Worksheet worksheet = (Excel._Worksheet)workbook.ActiveSheet;
 Excel._Worksheet worksheet = (Excel._Worksheet)workbook.ActiveSheet;

And these two lines to close/save the sheet.

  workbook.Save();
  workbook.Close();

The problem I'm having is that the EXCEL process is still active. (I used task manager to check.) And after reading/ writing data to the worksheet I have like 20 EXCEL processes active.

If anyone can show me a technique of ending the excelapp proc right after i close the workbook that would be great.

Many thanks, Aaron.

Upvotes: 2

Views: 5601

Answers (2)

kyrylomyr
kyrylomyr

Reputation: 12632

Simply call

excelapp.Quit();

after all work with Excel.

If processes still running, try to use Marshal.ReleaseComObject on all Excel objects and force an immediate garbage collection:

System.Runtime.InteropServices.Marshal.ReleaseComObject(excelapp);
excelapp = null;
GC.Collect();
GC.WaitForPendingFinalizers();

Note, that you need to use ReleaseComObject not only with your excelapp object, but also with every workbook and worksheet, that you had used.

Upvotes: 5

Hans Olsson
Hans Olsson

Reputation: 55001

Archer is on the right track with ReleaseComObject, but if you need to mess about with the garbage collection, then you've made a mistake in your automation code.

The most likely cause for it not closing down is that you have orphan references to some object that you can't release since you didn't store it in a variable. A common reason for this is if you access multiple "layers" in one call.

For example, if you do something like:

Workbooks("Book1").Sheets("Sheet1").Range("A1:A2").Value = 1;

Then you will have created references to a Workbook, a Sheet and a Range (and maybe the Sheets collection too?), none of which you can release properly.

So instead you have to split it up into steps with something like this (written completely from memory and from a late binding point of view and I might have missed out something else you need to release):

object wb = Workbooks("Book1");
object sheet = wb.Sheets("Sheet1");
object range = sheet.Range("A1:A2");
range.Value = 1;

Marshal.ReleaseComObject(range);
Marshal.ReleaseComObject(sheet);
Marshal.ReleaseComObject(wb);

Under normal circumstances you shouldn't have to kill the process or force garbage collection, and the only times I can remember having to do so was when I had bugs in my code.

Upvotes: 5

Related Questions