关于asp.net:Killing Excel.EXE在服务器上

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吗?你可以在完成excelobject.Quit();后关闭Excel应用程序,它对我很有用,但我不再在服务器端使用Excel。

您可以查看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

这对我真的很管用。