Killing Excel.EXE on server
0
假设一个ASP.NET Web应用程序在服务器上生成自动化的Excel报告。一旦处理结束,我们如何终止服务器端的excel.exe?我有目的地提出这个问题,因为我相信垃圾收集器不会清除Excel可执行文件,即使在Excel文件关闭之后也是如此。
有什么建议有用吗?
很抱歉这么说,我不想变聪明,但是…不要把Office放到服务器上!!!!
如果我理解正确的话!:)
编辑:尽管我已经为此被打了折扣,但我永远也不会提倡在服务器上运行Office——这在过去已经被证明对我来说是一件非常痛苦的事情。
说了这句话,我和Crystal Reports现在也一样;-)
我同意不在服务器上运行Office。在这件事上我别无选择。)
在使用taskkill选项时要记住的一件事是,除非您特别计划使用它(又称为singleton),否则您可能会运行多个Excel(或任何其他Office应用程序)副本,并且无意中关闭了错误的实例。
另请注意,根据http://support.microsoft.com/kb/257757
0另一种选择是,有一个名为Aspose Cells的产品,它提供了一个设计为允许您在服务器环境中以编程方式使用Excel工作表的产品。作为免责声明,我从来没有亲自使用过这个产品,但我从过去与我合作过的几个人那里听说过这个产品。
我有更多的时间来考虑这个答案,现在建议使用XML方法和开放式XML Office电子表格格式。
下面是一些很好的链接,可以开始用代码构建Office文档。http://msdn.microsoft.com/en-us/magazine/cc163478.aspxhttp://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx
只需在SQL Server上使用SSIS。它提供了导出到Excel的能力。不要在服务器上运行Office。交替地把钱浪费在一张纸或一张纸上。
GC确实有效,只是没有正确地使用它,遵循这个模式…
2获取Excel操作类以实现IDisposable,然后将killExcel()粘贴到Dispose方法中。
更新:还要注意,有时开发人员仍然会看到Excel.exe在任务管理器中运行。在假定上述代码不起作用之前,请检查运行代码的进程是否也已关闭。如果是VSTO或COM加载项,请检查Word/PowerPoint/Other Excel实例是否也已关闭,因为仍有返回启动进程的GC根。关闭后,Excel.exe进程将关闭。
我也遇到过类似的问题。当"taskkill excel.exe"或枚举所有"excel"进程并杀死它们时,这会杀死所有正在运行的excel进程。你最好只杀掉你目前正在处理的实例。
这是我用来实现这一点的代码。它使用pinvoke(请参见此处)从excel.application实例(下面的示例中是me.excel实例)获取processID。
1 2 3 4 5 6 7 | 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进行比较来找到正确的PID。
1 2 3 4 5 6 7 8 | '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 |
这不是找到正确进程的可靠方法,因为对于多个进程,基址有时似乎是相同的(导致删除错误的PID)。
你在使用vsto吗?你可以在完成
您可以查看Excel的XML模式来构建不带Excel本身的Excel文件。查看carlosag excel writer,它的功能完全相同。
:)我在这里草草记下了与Excel的冲突。它也有一些链接,我在一些繁重的搜索后发现。希望它有帮助。基本上,Excel是一种痛苦,尽管它可以自动化。
你需要的命令是"taskkill"。
http://technet.microsoft.com/en-us/library/bb491009.aspx
1 | > taskkill excel.exe |
我使用电子表格工具在服务器上生成XL报告,它工作得非常好。我们不必担心Excel过程。
我也不建议在服务器上使用Office应用程序,除了对mdb文件的数据访问。
我完全可以理解,有时候需要这样做。在这些案件中我建议如下:
- 创建一个单独的服务器,它是唯一的功能。(让我们以最小的影响重新启动)。
- 让服务器实现排队请求的机制
- 保留处理队列的单个线程。这使您能够跟踪Office应用程序,必要时终止它,并在不影响任何排队作业或其他应用程序的情况下继续运行。
如果您绝对需要在同一台服务器上完成这项工作,那么至少要在自己的应用程序池中实现上述功能。
限制自己保留一个工作队列,并且只有一个Excel实例(或任何其他Office应用程序)允许您使用taskkill或.kill()放弃它,而不丢失工作。
我相信如果你把它保持在一条线上,那么你很少有必要杀死它。
最好的方法是使用专门构建的库(如aspose中的库)来生成电子表格或填充模板。下一个最好的方法是,如果您需要的话,使用XML格式的Office。有时适合的一种轻量级方法是创建一个HTML文件,其中包含一个表,并以.xls扩展名命名该文件。Excel会很高兴地看到这一点,但它的功能非常有限。
这些是我使用过的选项(但不多)。还有一个叫做MicrosoftOfficeSharePointServer的东西,但我不知道它到底能让你做多少。
也就是说,您的问题发生的原因是,当您调用常规Excel库时,实际上是完全独立于.NET旋转Excel,实际上只是与代理库一起工作来与之交谈。这和您在WCF和服务中所拥有的几乎是一样的。您不会仅仅因为客户机应用程序使用它就期望服务终止。更糟糕的是,Excel是一个非托管资源,不会被释放/最终确定/垃圾收集。.NET运行时不知道Excel,它只知道那些代理。application.quit是您需要的,而且您可能需要显式释放所创建的COM对象。
实际上,我有一个类似于这个问题的问题——在使用Office自动化时检查挂起的Office进程——对那个问题的一些回答可能对您有用。
另外,我必须同意其他人所说的关于将任何Office产品远离服务器的说法;但是,由于您正在使用Excel,因此生成Excel XML文档可能是可行的。您可以这样做而不必进行任何办公室自动化,而且过程相当简单。对于简单的基于网格的电子表格,我发现它比使用Excel实现自动化要容易一些。OfficeOpenXML非常强大,它允许进行更复杂的报告,也可以进行更多的工作。
我遇到了类似的问题,使用了以下代码:
2这工作得很好,但我真的会考虑在服务器上使用Office。
结束工作后,您需要安全地释放所有COM互操作对象。"all"的意思是绝对的all:集合属性值等等。我已经创建了堆栈对象,并在设置期间推送了对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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还在,你必须手动终止它。
我在这个链接上找到了一个很好的解决方案:http://www.antinoline.com/showthread.php?t=277640
这对我真的很管用。