<p>I have a Visual Basic .NET program which needs to open and close an Excel spreadsheet.  Opening and reading the spreadsheet work fine, but trying to close the Excel 2007 application causes it to hang.  It seems to close, but if you look in the task manager the application is still running.  The code that I'm using to close it is</p>

<pre><code>wbkData.Close(saveChanges:=False)
appExcel.Quit()
wbkData = Nothing
appExcel = Nothing
</code></pre>

<p>How can I get Excel to close properly?</p>

I found a
solution in the MSDN Excel Blog
which worked for me.  It's explained as
There are two problems with the above:
(1) Although the code appears to
  dispose of the 'wbkData' object first,
  etc., the code above does not actually
enforce
this as the .NET Garbage Collection procedure can dispose of
  its objects in any order. (GC is
  non-deterministic in order, not just
  non-deterministic in timing.)
(2) Commands such as 'wsh =
  wbkData.Workssheets.Item(1)' -- or
  lines like it -- are very common and
  will create an RCW object wrapping a
  'Worksheets' object. You won't have a
  variable holding a reference to it, so
  you don't generally think about it,
  but this RCW object will not be
  disposed until the next Garbage
  Collection. However, the code above
  calls GC.Collect()
last
, and so the
  RCW is still holding a reference to
  this 'Worksheets' object when
  appExcel.Quit() is called. Excel hangs
  as a result.
The final code looks like
```
```
GC.Collect()
GC.WaitForPendingFinalizers()

wbkData.Close(SaveChanges:=False)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wbkData) : wbkData = Nothing
appExcel.Quit()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(appExcel) : appExcel = Nothing
```
```