4

I've seen a lot of articles and questions about how to be sure that Excel actually quits when you want it to and the process doesn't stay alive. Here is a knowledge Base article describing the problem and Microsoft's recommended solution. Essentially:

'close files

'Quit Excel
xlApp.quit()

'Release and collect garbage
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)
GC.Collect()
GC.WaitForPendingFinalizers()

Many people don't recommend killing the process; See How to properly clean up Excel interop objects and Understanding Garbage Collection in .net

On the other hand many people don't recommend using GC.Collect. See What's so wrong about using GC.Collect()?

In my experience killing the process is the fastest and easiest way to be sure that Excel is gone. My code kills only the exact process that it starts, no other. I make sure to Close any open workbooks, Quit the application and Release the xlApp object. Finally I check to see if the process is still alive and if so then kill it.

<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
ByRef lpdwProcessId As Integer) As Integer
    End Function

Sub testKill()

    'start the application
    Dim xlApp As Object = CreateObject("Excel.Application")

    'do some work with Excel

    'close any open files

    'get the window handle
    Dim xlHWND As Integer = xlApp.hwnd

    'this will have the process ID after call to GetWindowThreadProcessId
    Dim ProcIdXL As Integer = 0

    'get the process ID
    GetWindowThreadProcessId(xlHWND, ProcIdXL)

    'get the process
    Dim xproc As Process = Process.GetProcessById(ProcIdXL)

    'Quit Excel
    xlApp.quit()

    'Release
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)

    'set to nothing
    xlApp = Nothing

    'kill the process if still running
    If Not xproc.HasExited Then
        xproc.Kill()
    End If

End Sub

I've seen a lot of people say that killing the process is bad, but I haven't seen any qualitative answers on why. Especially after making sure that files are closed, Excel has quit and we'll only kill the exact process that we started. My question is what are the potential problems with killing the Excel process. Does it hurt perfomance? Will it harm Excel?

Many will also say that with good coding I don't have to kill the process. Maybe, but that doesn't answer the question of "Why is it bad to kill the process?" After closing the files, quitting Excel and releasing the objects; why would it be a bad thing to just make absolutely sure the process is gone?

Edit: Also what is actually left after Excel quits? If Excel was visible, it appears to quit normally, disappearing from view and from the taskbar. So did Excel actually quit or didn't it. It seems to me that Excel actually did quit and that we only have an empty process shell running. Can anyone comment on that?

Edit: It is interesting to me to note that GC (aka Garbage Collection) via GC.Collect() GC.WaitForPendingFinalizers() will actually release the process shell that is left behind after Excel quits. Does that support my assumption that the empty process shell really is garbage after all?

Edit: just found an excellent website on the problem: 50 Ways to kill Excel

Community
  • 1
  • 1
D_Bester
  • 5,723
  • 5
  • 35
  • 77
  • 4
    Killing a process is like shutting down your computer by jerking the power cord from the wall. Sure, it *works*, but it's not the correct way to close a program. – Cody Gray - on strike Jul 22 '13 at 07:09
  • @CodyGray Modern Machines are designed to recover from jerking the power cord out reasonably well. You'll only loose something if you havn't saved it yet. I guess he's wondering wether with modern Excel does the same apply? – Toby Allen Jul 22 '13 at 07:14
  • @CodyGray But what can really happen in my Excel case? Will I lose information? Will the computer hate me? Actually Excel has already quit. So isn't it true that the only thing left is memory objects that refused to die? – D_Bester Jul 22 '13 at 07:17
  • 3
    @Toby I disagree. Yes, work has been done to try to prevent things from going as wrong as they used to, but that still doesn't mean it's a valid way to shut down your system. Safety engineers work on cars to make sure that you don't die when you have an accident, too, but that's doesn't mean you don't need to drive safely. So yes, Windows generally cleans up after terminated processes, but that doesn't make it the right thing to do. – Cody Gray - on strike Jul 22 '13 at 07:17
  • What if the user has some other Excel sheets open? Also, the problem is not only that Excel stays open when you missmanage the Interop objects but also that it acts more sluggish and unreliable if you are neglecting managing objects. – Christian Sauer Jul 22 '13 at 07:17
  • @ChristianSauer Actually the user never interacts with my hidden Excel instance. And my code never terminates any other instance. – D_Bester Jul 22 '13 at 07:19
  • @D_Bester, I wrote a singleton which is responsible for opening and closing excel instances. I have never had a memory leak issue, performance issue or any other form of residual issue. As long as you ensure that the instance you open is the one you close, i just see it as making up for faults in the Excel API – David Colwell Jul 22 '13 at 07:35
  • 2
    @DavidColwell I have written many applications that use Excel to perform some important job and have had many problems with Excel process not closing after doing something in Excel. – D_Bester Jul 22 '13 at 08:03
  • 1
    I find that getting rid of excel.exe requires three things: set any and all references to excel application to null/nothing, `GC.Collect()`, *and* the application must have been closed, either by the user or by calling `Quit`, and if the user cancels the close that doesn't count. When I do all this, I only get extra excel.exes when debugging (since stopping execution won't clean up.) – Dave Cousineau Jul 22 '13 at 08:19
  • I've never had much luck with Office Automation (problems you state, portability, etc.) - now I just write Word/Excel VBA to do the host the code and launch the Word/Excel "program" to do the work. Word seems to clean up after itself just fine. I haven't tried this on a server with a massive number of events so it may not work in all cases. – rheitzman Jul 22 '13 at 17:52

3 Answers3

6

Look, the fact of the matter is, you should always let the app exit normally if at all possible. Killing the app is a last resort. I understand you're convinced that you don't see anything wrong with doing it in this case, and maybe you're correct. Even if there are absolutely no negative affects to your system from killing it, That doesn't change the fact that it's the wrong thing to do. It's like breaking the law because you know you won't get caught, and it's a victimless crime anyways.

There are, however, potential side-effects that you may not realize. For example, when you forcefully terminate an app, the OS may retain crash data for it. Or it may send crash telemetry to Microsoft. You're essentially telling Microsoft that apps are crashing more often then they actually are, causing their crash statistics to be slightly skewed.

Another possible side effect is that registry hives may not unload correctly. You may have seen this error in the event log from time to time. It typically happens when an app is forcefully closed and it did not close the handles to the registry correctly.

Even if none of those things happen, you can't know what a future version of the OS might do. What works today, might not work tomorrow. This is why you should ALWAYS follow the documented API's and guidelines, because they typically will work very hard to support something they've published, but will typically not work very hard to support something they've specifically told you not to do.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • 1
    Yeah, as long as software developers continue to do stuff like this, users will always wonder why the performance and stability of their machines seems to degrade over time and they have to reinstall the operating system. – Cody Gray - on strike Jul 22 '13 at 08:04
  • 1
    It gets a bit subjective here, but it is not "breaking the law" to kill Excel. You have to do it because otherwise you will have to reboot your computer when you have 20 or more "invisble" Excel processes running on your system. This is the fault of Excel and not the user. Killing Excel will not lead to telemetry data being sent and you don't get registry hive unload problems if you kill a process. The OS will ensure that all open registry handles are closed when the process is killed allowing the hive to unload when logging out. Furthermore, this is an Office issue and not an OS issue. – Martin Liversage Jul 22 '13 at 08:46
  • 2
    Are you sure this is not a *programmer* issue, that not all open references to existing objects have been removed so that the application is allowed to quit normally? – Lasse V. Karlsen Jul 22 '13 at 08:58
  • Lasse is onto something. The code *does* try to quit Excel in the normal way, calling the `quit` method. Then it checks to see if it has exited, and if not, kills it. There should also be an assertion inside that if statement, and some debugging needs to figure out *why* Excel hasn't quit like you asked it to yet. – Cody Gray - on strike Jul 22 '13 at 09:13
  • 2
    @CodyGray Actually we do know why Excel shell process doesn't quit. Microsoft has helpfully pointed out that unmanaged COM references are counted and once they are all released then Excel should quit. Yet after spending hours debugging and counting references, I concluded that it was simply a waste of time. So now the question is why is it bad to kill the empty process shell after Excel has already exited. I invite you to put up your own answer and let other users vote you up if they like your answer. I already know you don't like my answer, but that's OK. Your input is very helpful. – D_Bester Jul 22 '13 at 10:47
4

When you use automation to control an Office application from another application you will occasionally have to kill the Office process like you do to avoid "leaking" invisible Office applications. This is an unfortunate result of how the Office applications tries to act both as an end-user application and also as an automation server.

I resorted to more or less the same solution as you when using Word on the server side (don't ask why). No matter how much effort we put into shutting Word down properly an increasing number of "invisble" Word processes would accumulate on the server. The only good solution was to kill thoses processes that wouldn't terminate after being instructed to quit.

When a Windows process is killed all resources used by the process is cleaned up by the operating system, e.g. files and other operating system handles like registry handles are closed, memory is freed etc. From the operating system point of view nothing is leaked when a process is terminated.

However, the application may create temporary files that it intend to delete during normal shutdown. Over time these orphaned files may use an increasing amount of space on the disk. Also, if the user has other files open in the application these files may be left in an inconsistent state when the process is terminated and unsaved changes may be lost. Basically, what an application that is killed can "leak" is files that it intend to clean up or delete when it shuts down. Another source of "leaks" are resources acquired on the network (e.g. files open on shares). However, when the process is terminated the network handle will eventually become "stale" and reclaimed by the network server.

Also, I would like to note that Dr. Watson will not collect any crash dump data if a process is killed. This only happens if a process crashes unexpectedly (e.g. has an unhandled exception).

The bottom line: If you are careful killing Excel is probably the best way to avoid "leaking" invisble Excel processes over time. The alternative of letting them run using more and more system resources until the system is restarted is not viable. The cost, if any, should be nothing more than some small files left in the temporary folder.


As an alternative to automating Office you can use the Open XML SDK to open and modify Office files. Initially it might be somewhat more complex but you completely avoid spinning up the heavy Office applications in the process.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • 1
    Do you have a link to some official documentation that guarantees that "from the operating system point of view nothing is leaked when a process is terminated"? Yes, the OS tries to clean up after you, but it's just a safety net to catch the stuff that the developer may have missed. You're not supposed to count on this behavior. I suppose from the OS's perspective, everything is hunky-dory, but the app you're killing may not share this perspective. – Cody Gray - on strike Jul 22 '13 at 08:07
  • 1
    @CodyGray: Any proper operating system with processes will clean up all resources used by the process when it is terminated. That is the basic promise of the operating system. If anything is "leaked" it happens in the kernel (i.e. a driver or OS bug) because the process is completely gone. – Martin Liversage Jul 22 '13 at 08:18
  • 1
    Asking for links to documentation with guarantees fundamental behavior of an OS is a little like asking for guarantees that pressing the brake pedal in a car will stop the car. Finding that in print is perhaps not so easy. However, I can recommend reading books like [Operating Systems Design and Implementation](http://www.amazon.com/Operating-Systems-Design-Implementation-Edition/dp/0131429388) and [Windows Internals](http://www.amazon.com/Windows%C2%AE-Internals-Including-Windows-Developer/dp/B00B9ZDLPQ). – Martin Liversage Jul 22 '13 at 08:38
  • 1
    "Any proper operating system" - is a non-sequiter. First, all OS's have bugs, and Windows has been known for it's resource leak bugs even after killing processes. Kernel32 and GDI32 often leak handles that never get cleaned up, this is because these are shared processes for performance reasons and bugs in these systems lead to problems in shared resources. Second, I didn't say anything about Dr. Watson, Windows collects lots of telemetry data that is unrelated to Watson. – Erik Funkenbusch Jul 22 '13 at 14:01
0

In my experience there are a few things that a program does when it shuts down:

  1. Release all memory references
  2. Delete any temporary or work files
  3. Save any State data

For these reasons, it is critical that you shut down Excel in the manner which the API describes, using app.Quit(). Where this example deviates from the Norm, is that the API does not release all the COM objects. This leads to step 1) being incomplete. There is no way to ensure that the application shuts down effectively in all cases, as you may not always have control over what COM objects are created.

I have found the best way to utilize Excel (among other office programs) is to use the following process:

  1. Get a list of process IDs with the name containing Excel
  2. Open Excel
  3. Repeat Step 1. Use this to determine the process ID of the new Excel instance you created
  4. Use Excel
  5. Quit Excel, releasing all objects you created and terminating with Application.Quit()
  6. Kill the process

This gives Excel the opportunity to release any objects, delete any temp files and save any state data before the process is terminated. I generally create a singleton class which is responsible for managing excel instances. It implements IDisposable, and on Disposal, it will quit all remaining Excel applications.

David Colwell
  • 2,450
  • 20
  • 31
  • 1
    I recommend you use App.HWND > GetWindowThreadProcessId(xlHWND, ProcIdXL) > Process.GetProcessById(ProcIdXL) instead of steps 1 and 3 (see my question above for how I do it) – D_Bester Jul 22 '13 at 23:38
  • Also doesn't Excel delete temp files and save state data when it quits? If so what is really left in the process? I suspect that the Excel process left behind is really just an empty shell that doesn't contain Excel at all. It is just the left over memory pointers that need removed. – D_Bester Jul 22 '13 at 23:42
  • You are correct, and the gist of my argument is that you *should* call the Quit function (so Excel can do all its cleanup), and all that is left is an empty shell with some random COM objects attached, so killing the empty shell is fine. On a related note, Why use app.HWND? Is it more reliable? – David Colwell Jul 23 '13 at 00:05
  • App.HWND gets you the correct window handle from which you can get the process ID. This way you are confident you have the correct process without bothering with the entire list of process IDs. And it avoids the unlikely scenario of a second Excel instance started in the exact moment of starting Excel before you get the second list. Using App.HWND is more reliable. – D_Bester Jul 23 '13 at 00:20
  • And of course I fully agree with using App.Quit to exit Excel. – D_Bester Jul 23 '13 at 00:21
  • I noticed the process sticking around and followed the advice in the very first link given by the OP. Doing that seemed to reliably close everything up and I no longer see Excel in the task list. It seems to address releasing all COM objects as per your concern here. – dudeNumber4 Jan 19 '15 at 14:31