<blockquote>
  <p><strong>Possible Duplicate:</strong><br>
  <a href="https://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c">How to properly clean up Excel interop objects in C#</a>  </p>
</blockquote>



<p>Suppose a ASP.NET web application generates automated Excel Reports on the server. How do we kill a server-side Excel.EXE once the processing is over. I am raising this purposely, because I believe that the Garbage Collecter does not clean the Excel executable even after the Excel file is closed.</p>

<p>Any pointers would be helpful?</p>

[{'answer_id': 51467, 'author': 'Mark Ingram', 'author_id': 986, 'author_profile': 'https://Stackoverflow.com/users/986', 'pm_score': 2, 'selected': False, 'text': '<p>The command you need is "taskkill".</p>\n\n<p><a href="http://technet.microsoft.com/en-us/library/bb491009.aspx" rel="nofollow noreferrer">http://technet.microsoft.com/en-us/library/bb491009.aspx</a></p>\n\n<pre><code>&gt; taskkill excel.exe\n</code></pre>\n'}, {'answer_id': 51468, 'author': 'Biri', 'author_id': 968, 'author_profile': 'https://Stackoverflow.com/users/968', 'pm_score': 2, 'selected': False, 'text': '<p>Are you using VSTO? You can close the Excel app after you finished with <code>excelobject.Quit();</code> It worked for me, but I don\'t use Excel on server-side anymore.</p>\n\n<p>You can have a look on Excel\'s XML schema to build the Excel file without Excel itself. Check out <a href="http://www.carlosag.net/Tools/ExcelXmlWriter/Default.aspx" rel="nofollow noreferrer">CarlosAg Excel Writer</a>, which does exactly the same.</p>\n'}, {'answer_id': 51469, 'author': 'Galwegian', 'author_id': 3201, 'author_profile': 'https://Stackoverflow.com/users/3201', 'pm_score': 4, 'selected': False, 'text': "<p>Sorry to say this, and I'm not trying to be smart, but... <strong>don't put office on the server!!!</strong></p>\n\n<p>That's if I've understood correctly! :)</p>\n\n<p><strong>EDIT:</strong> Even though I've been marked down for this, I will never <em>ever</em> advocate running Office on the server - it has proven <strong>way too</strong> much of a pain in the ass for me in the past.</p>\n\n<p>Having said that, the same now goes for me and Crystal Reports ;-)</p>\n"}, {'answer_id': 51472, 'author': 'Gishu', 'author_id': 1695, 'author_profile': 'https://Stackoverflow.com/users/1695', 'pm_score': 2, 'selected': False, 'text': '<p>:). I jotted down my skirmish with Excel <a href="http://madcoderspeak.blogspot.com/2006/07/die-die-excel-you-fiend.html" rel="nofollow noreferrer">here</a>. It also has some links that I found after some heavy searching. Hope it helps.<br>\nBasically Excel is a pain even though it can be automated.</p>\n'}, {'answer_id': 51489, 'author': 'Artem Tikhomirov', 'author_id': 2313, 'author_profile': 'https://Stackoverflow.com/users/2313', 'pm_score': 0, 'selected': False, 'text': '<p>You need safely dispose all COM interop objects after you end your work. By "all" I mean absolutely <strong>all</strong>: collections property values and so on. I\'ve created stack object and pushed objects during their setup:</p>\n\n<pre><code>Stack&lt;object&gt; comObjectsToRelease = new Stack&lt;object&gt;();\n...\nLog("Creating VBProject object.");\nVBProject vbProject = workbook.VBProject;\ncomObjectsToRelease.Push(vbProject);\n...\nfinally\n{\n    if(excel != null)\n    {\n        Log("Quiting Excel.");\n        excel.Quit();\n        excel = null;\n    }\n    while (comObjectsToRelease.Count &gt; 0)\n    {\n        Log("Releasing {0} COM object.", comObjectsToRelease.GetType().Name);\n        Marshal.FinalReleaseComObject(comObjectsToRelease.Pop());\n    }               \n    Log("Invoking garbage collection.");\n    GC.Collect();\n}\n</code></pre>\n\n<p>If Excel is still there you have to kill it manually.</p>\n'}, {'answer_id': 51600, 'author': 'Fabian', 'author_id': 3862, 'author_profile': 'https://Stackoverflow.com/users/3862', 'pm_score': 0, 'selected': False, 'text': '<p>I had a similar problem and used the following code:</p>\n\n<pre><code>System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses();\nfor (int i = 0; i &lt; procs.Length; i++)\n{\n  if(procs[i].ProcessName == "EXCEL")\n  {\n    procs[i].Kill();\n  }\n}\n</code></pre>\n\n<p>This worked pretty well, but I would really think about working with Office on a server.</p>\n'}, {'answer_id': 51652, 'author': 'bruceatk', 'author_id': 791, 'author_profile': 'https://Stackoverflow.com/users/791', 'pm_score': 1, 'selected': False, 'text': "<p>I also would not recommend using office apps on a server except for data access to mdb files.</p>\n\n<p>I can definitely understand that there are times where it is necessary.  In thoses cases \nI would recommend the following:</p>\n\n<ul>\n<li>Create a separate server where that is the only function.  (Let's you reboot with minimum impact).</li>\n<li>Have the server implement a mechanism of queuing requests</li>\n<li>Keep a single thread processing the queue.  This gives you the ability to keep track of the office app, kill it if necessary, and continue on without impacting any queued up jobs or other applications.</li>\n</ul>\n\n<p>If you absolutely need to do it on the same server, then at least implement the above in it's own app pool.</p>\n\n<p>Limiting yourself keeping a queue of work and only one instance of Excel (or any other office app) let's you kill it with abandon with TaskKill or .Kill() and not lose work.  </p>\n\n<p>I believe if you keep it to a single thread then you would rarely have a need to kill it.</p>\n"}, {'answer_id': 51755, 'author': 'Jason Z', 'author_id': 2470, 'author_profile': 'https://Stackoverflow.com/users/2470', 'pm_score': 3, 'selected': False, 'text': '<p>I agree with not running Office on a server.  Not that I have any choice in the matter :)</p>\n\n<p>One thing to keep in mind with the taskkill option, is that unless you specifically plan for it (aka - singleton), you may have multiple copies of Excel (or any other Office app) running, and unintentionally close the wrong instance.</p>\n\n<p>Also note that per <a href="http://support.microsoft.com/kb/257757" rel="noreferrer">http://support.microsoft.com/kb/257757</a></p>\n\n<blockquote>\n  <p>Microsoft does not currently\n  recommend, and does not support,\n  Automation of Microsoft Office\n  applications from any unattended,\n  non-interactive client application or\n  component (including ASP, ASP.NET,\n  DCOM, and NT Services), because Office\n  may exhibit unstable behavior and/or\n  deadlock when Office is run in this\n  environment.</p>\n</blockquote>\n\n<p>As an alternative, there is a product called <a href="http://www.aspose.com/categories/file-format-components/aspose.cells-for-.net-and-java/default.aspx" rel="noreferrer">Aspose Cells</a> that offers a product that is designed to allow you to programmatically work with an Excel sheet in a server environment.  As a disclaimer, I have never personally used this product, but I have heard about it from several people I worked with in the past.</p>\n'}, {'answer_id': 51767, 'author': 'rjzii', 'author_id': 1185, 'author_profile': 'https://Stackoverflow.com/users/1185', 'pm_score': 0, 'selected': False, 'text': '<p>I actually had a question that was similar to this awhile back - <a href="https://stackoverflow.com/questions/9905/check-for-hung-office-process-when-using-office-automation">Check for hung Office process when using Office Automation</a> - some of the responses to that question might be useful for you.</p>\n\n<p>Also, I have to agree with what everyone else is saying in regards to keeping any Office products off of a server; however, since you are doing Excel, it might be feasible for you to generate <a href="http://office.microsoft.com/en-us/excel/HA102063961033.aspx" rel="nofollow noreferrer">Excel XML documents</a>. You can do this without having to do any Office automation and the process is fairly straightforward. For simple grid based spreadsheets I have found it to be a bit easier than trying to automate it using Excel. The <a href="http://en.wikipedia.org/wiki/Office_Open_XML" rel="nofollow noreferrer">Office Open XML</a> is quite powerful and allows for more complex reports are possible as well some more effort. </p>\n'}, {'answer_id': 312513, 'author': 'Vincent Van Den Berghe', 'author_id': 39259, 'author_profile': 'https://Stackoverflow.com/users/39259', 'pm_score': 2, 'selected': False, 'text': '<p>I\'ve had a similar problem. While \'taskkill excel.exe\' or enumerating all "excel" processes and killing them does work, this kills ALL running Excel processes. You\'re better off killing only the instance you\'re currently working with.</p>\n\n<p>Here\'s the code I used to accomplish that. It uses a PInvoke (see <a href="http://www.pinvoke.net/default.aspx/user32/GetWindowThreadProcessId.html" rel="nofollow noreferrer">here</a>) to get the ProcessID from the Excel.Application instance (Me.ExcelInstance in the example below).</p>\n\n<pre><code>Dim ExcelPID As Integer\nGetWindowThreadProcessId(New IntPtr(Me.ExcelInstance.Hwnd), ExcelPID)\n\nIf ExcelPID &gt; 0 Then\n   Dim ExcelProc As Process = Process.GetProcessById(ExcelPID)\n   If ExcelProc IsNot Nothing Then ExcelProc.Kill()\nEnd If\n</code></pre>\n\n<p>Please not this might not work on all platforms because of the PInvoke... To date, this is the only method I have found to be reliable. I have also tried to find the correct PID by enumarating all Excel processes and comparing the Process.MainModule.BaseAddress to the Excel.Application.Hinstance.</p>\n\n<pre><code>\'DO NOT USE THIS METHOD, for demonstration only    \nFor Each p as Process in ExcelProcesses\n        Dim BaseAddr As Integer = p.MainModule.BaseAddress.ToInt32()\n        If BaseAddr = Me.ExcelInstance.Hinstance Then\n            p.Kill()\n            Exit For\n        End If\nNext\n</code></pre>\n\n<p>This is <strong>not</strong> a reliable way to find the correct process, as the BaseAddress sometimes seems to be the same for several processes (resulting in killing the wrong PID).</p>\n'}, {'answer_id': 364012, 'author': 'MOZILLA', 'author_id': 38997, 'author_profile': 'https://Stackoverflow.com/users/38997', 'pm_score': 1, 'selected': False, 'text': '<p>I have used <a href="http://spreadsheetgear.com/" rel="nofollow noreferrer">spreadsheetgear</a> to generate XL reports on the server and it works really well. We don\'t have to worry about the EXCEL process..</p>\n'}, {'answer_id': 1309401, 'author': 'Anonymous Type', 'author_id': 141720, 'author_profile': 'https://Stackoverflow.com/users/141720', 'pm_score': 2, 'selected': False, 'text': '<p>I\'ve had more time to think about this answer, and would now recommend using an XML approach with the Open XML Office spreadsheet format.</p>\n\n<p>Heres some good links to get started on building a office document with code.\n<a href="http://msdn.microsoft.com/en-us/magazine/cc163478.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/magazine/cc163478.aspx</a>\n<a href="http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx</a></p>\n\n<p>Just use SSIS on SQL Server. It provides the ability to export to Excel.\nDon\'t run office on the server. Alteranatively waste money on aspose or spreadsheetgear.</p>\n\n<p>GC does work your just not using it properly follow this pattern...</p>\n\n<pre><code>   private void killExcel()\n        {\n          xlApp.Quit();\n          Marshal.ReleaseCOMObject(xlApp);\n          if(xlApp != null)\n          {\n            xlApp = null;\n          }\n          GC.WaitForPendingFinalizers();\n          GC.Collect();\n          GC.WaitForPendingFinalizers();\n          GC.Collect();\n        }\n</code></pre>\n\n<p>get your Excel operational class to implement IDisposable, and then stick killExcel() in the Dispose method.</p>\n\n<p>UPDATE: Also note that sometimes dev will still see Excel.exe running in task manager. Before assuming the above code isn\'t working, check that the process that is running the code is also closed. In the case of a VSTO or COM addin, check that Word/powerpoint/other excel instance is also closed as there is still a GC root back to the launching process. Once that is closed the Excel.exe process will close.</p>\n'}, {'answer_id': 3936464, 'author': 'Jim L', 'author_id': 195693, 'author_profile': 'https://Stackoverflow.com/users/195693', 'pm_score': 0, 'selected': False, 'text': "<p>The best approach is to use a purpose built library such as the one from Aspose to generate the spreadsheets or populate templates. The next best approach is to use the xml formats for office if practical for your needs. A lightweight approach that is sometimes suitable is to create an HTML file with one table in it and name it with an .xls extension. Excel will happily read that, but it is very limited in what it can do.</p>\n\n<p>Those are the options I've used (but not much). There's also a thing called Microsoft Office Sharepoint Server, but I've no idea how much it really lets you do.</p>\n\n<p>That said, your problem is happening because when you invoke the regular Excel libraries, you're actually spinning up Excel completely independently of .Net and actually just working with a proxy library to talk to it. This is pretty much the same kind of thing you'd have with WCF and a service. You wouldn't expect the service to die just because the client application was done using it. Worse, Excel is an unmanaged resource and will not be disposed/ finalized/ garbage collected at all. The .Net Runtime doesn't know about Excel, it just knows about those proxies. Application.quit is what you need and also you may need to explicitly release the com objects that are created.</p>\n"}]
['https://Stackoverflow.com/questions/51462', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/4021/']