在服务器上杀死Excel.EXE

可能重复:
如何正确清理C#中的Excel互操作对象

假设ASP.NET Web应用程序在服务器上生成自动Excel报表。 一旦处理结束,我们如何杀死服务器端的Excel.EXE。 我故意提出这个问题,因为我相信,甚至在Excel文件closures后,垃圾收集器也不会清理Excel可执行文件。

任何指针会有帮助吗?

对不起,说这个,我不是想要聪明,但是… 不要把办公室放在服务器上!

那就是如果我理解正确的话! 🙂

编辑:即使我已经明确了这一点,我永远不会主张在服务器上运行Office – 它已经certificate了过去在我的屁股痛苦了。

话虽如此,现在对我和Crystal Reports也是如此;-)

我同意不在服务器上运行Office。 不是我在这个问题上有任何select:)

有一件事要记住taskkill选项,除非你专门计划它(又名 – 单身),你可能有多个Excel(或任何其他Office应用程序)的副本运行,并无意中closures了错误的实例。

另请注意,每个http://support.microsoft.com/kb/257757

Microsoft目前不推荐并不支持从任何无人参与的非交互式客户端应用程序或组件(包括ASP,ASP.NET,DCOM和NT服务)自动化Microsoft Office应用程序,因为Office可能会出现不稳定的行为和/或在此环境中运行Office时发生死锁。

作为替代scheme,还有一种名为“ Aspose Cells”的产品,它提供了一种产品,可让您以编程方式在服务器环境中使用Excel工作表。 作为一个免责声明,我从来没有亲自使用过这个产品,但是我从过去几个人那里听说过这个产品。

我有更多的时间思考这个答案,现在推荐使用Open XML Office电子表格格式的XML方法。

下面是一些很好的链接,开始构build一个包含代码的办公文档。 http://msdn.microsoft.com/en-us/magazine/cc163478.aspx http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx

只需在SQL Server上使用SSIS。 它提供了导出到Excel的function。 不要在服务器上运行办公室。 在aspose或spreadsheetgear上浪费金钱。

气相色谱工作,你只是没有正确使用它遵循这种模式…

private void killExcel() { xlApp.Quit(); Marshal.ReleaseCOMObject(xlApp); if(xlApp != null) { xlApp = null; } GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } 

让您的Excel操作类实现IDisposable,然后在Dispose方法中粘贴killExcel()。

更新:另外请注意,有时开发者仍然会看到Excel.exe在任务pipe理器中运行。 在假定上述代码不起作用之前,请检查运行代码的进程是否也closures。 在VSTO或COM插件的情况下,检查Word / powerpoint /其他excel实例是否也closures,因为仍然有一个GC根目录返回到启动进程。 一旦closures,Excel.exe进程将closures。

你在使用VSTO吗? 完成excelobject.Quit();后,可以closuresExcel应用程序excelobject.Quit(); 它为我工作,但我不再使用服务器端的Excel。

你可以看看Excel的XML模式来构build没有Excel本身的Excel文件。 看看CarlosAg Excel Writer ,它完全一样。

我有类似的问题。 虽然“taskkill excel.exe”或枚举所有“excel”进程并杀死他们确实工作,这将杀死所有运行的Excel进程。 只能杀死你当前正在使用的实例。

这是我用来完成的代码。 它使用PInvoke(请参阅此处 )从Excel.Application实例(下例中的Me.ExcelInstance)获取ProcessID。

 Dim ExcelPID As Integer GetWindowThreadProcessId(New IntPtr(Me.ExcelInstance.Hwnd), ExcelPID) If ExcelPID > 0 Then Dim ExcelProc As Process = Process.GetProcessById(ExcelPID) If ExcelProc IsNot Nothing Then ExcelProc.Kill() End If 

请不要这在所有的平台上都不起作用,因为PInvoke …迄今为止,这是我发现的唯一可靠的方法。 我也尝试通过鼓励所有Excel进程并将Process.MainModule.BaseAddress与Excel.Application.Hinstance进行比较来find正确的PID。

 'DO NOT USE THIS METHOD, for demonstration only For Each p as Process in ExcelProcesses Dim BaseAddr As Integer = p.MainModule.BaseAddress.ToInt32() If BaseAddr = Me.ExcelInstance.Hinstance Then p.Kill() Exit For End If Next 

不是一个可靠的方法来find正确的过程,因为BaseAddress有时似乎是几个进程相同(导致杀死错误的PID)。

你需要的命令是“taskkill”。

http://technet.microsoft.com/en-us/library/bb491009.aspx

 > taskkill excel.exe 

:)。 我用Excel 在这里记下了我的小冲突。 它也有我经过一些沉重的search后发现的一些链接。 希望能帮助到你。
基本上Excel是一个痛苦,即使它可以自动化。

我也不会build议在服务器上使用办公应用,除了数据访问mdb文件。

我当然可以明白,有时候这是必要的。 在这种情况下,我会build议如下:

  • 创build一个单独的服务器,这是唯一的function。 (让我们以最小的影响重新启动)。
  • 让服务器实现排队请求的机制
  • 保持单个线程处理队列。 这使您能够跟踪办公应用程序,必要时将其终止,并继续执行,而不会影响任何排队的作业或其他应用程序。

如果你绝对需要在同一台服务器上完成,那么至less应该在自己的应用程序池中实现上述function。

限制自己保持一个工作队列,只有一个Excel(或任何其他办公应用程序)的实例,让你杀了它放弃与TaskKill或.Kill(),而不是失去了工作。

我相信如果你把它保持在一个单一的线程,那么你很less有必要杀死它。

我用电子表格在服务器上生成XL报告,效果非常好。 我们不必担心EXCELstream程

我有一个类似的问题,并使用下面的代码:

 System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses(); for (int i = 0; i < procs.Length; i++) { if(procs[i].ProcessName == "EXCEL") { procs[i].Kill(); } } 

这工作得很好,但我真的想考虑在服务器上使用Office。

实际上我有一个类似于这个问题的问题 – 使用Office自动化检查挂起的Office进程 – 对这个问题的一些回应可能对您有用。

另外,我必须同意其他人在保持Office产品不在服务器上的说法。 但是,由于您正在执行Excel,因此您可能可以生成Excel XML文档 。 你可以做到这一点,而不必做任何办公自动化,这个过程是相当简单的。 对于简单的基于网格的电子表格,我发现它比使用Excel自动化它更容易一些。 Office Open XMLfunction非常强大,可以进行更复杂的报表,并且可以做更多的工作。

我在这个链接上find了一个很好的解决scheme: http : //www.antionline.com/showthread.php?t=277640

它真的为我工作。

结束工作后,您需要安全地处理所有COM互操作对象。 所有“我”的意思是绝对全部 :收集财产价值等等。 我已经创build堆栈对象,并在设置过程中推送对象:

 Stack<object> comObjectsToRelease = new Stack<object>(); ... Log("Creating VBProject object."); VBProject vbProject = workbook.VBProject; comObjectsToRelease.Push(vbProject); ... finally { if(excel != null) { Log("Quiting Excel."); excel.Quit(); excel = null; } while (comObjectsToRelease.Count > 0) { Log("Releasing {0} COM object.", comObjectsToRelease.GetType().Name); Marshal.FinalReleaseComObject(comObjectsToRelease.Pop()); } Log("Invoking garbage collection."); GC.Collect(); } 

如果Excel仍然在那里,你必须手动杀死它。

最好的方法是使用专门构build的库(如Aspose的库)生成电子表格或填充模板。 下一个最好的办法是使用xml格式的办公室,如果您的需要切合实际的话。 有时适合的轻量级方法是创build一个带有一个表格的HTML文件,并用一个.xls扩展名来命名。 Excel会高兴地阅读,但它可以做什么是非常有限的。

这些是我使用的选项(但不是很多)。 还有一个叫做Microsoft Office Sharepoint Server的东西,但是我不知道它真的可以让你做多less事情。

也就是说,你的问题正在发生,因为当你调用常规的Excel库的时候,你实际上完全独立于.Net而独立运行Excel,而实际上只是使用代理库来与之交谈。 这与WCF和一项服务有很多相同之处。 你不会期望这个服务会因为客户端应用程序的使用而死掉。 更糟糕的是,Excel是一个非托pipe资源,不会被处置/终结/垃圾收集。 .Net Runtime不知道Excel,只知道那些代理。 Application.quit是你需要的,你也可能需要明确地释放创build的com对象。