在服务器上杀死Excel.EXE

时间:2008-09-09 09:31:41

标签: asp.net excel

  

可能重复:
  How to properly clean up Excel interop objects in C#

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

任何指针都会有所帮助吗?

14 个答案:

答案 0 :(得分:18)

很抱歉这样说,我并不是想要聪明,但是...... 不要在服务器上任职!!!

如果我理解正确的话! :)

编辑尽管我已经为此进行了标记,但我永远不会提倡在服务器上运行Office - 它已经证明方式< / strong>过去对我来说很痛苦。

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

答案 1 :(得分:6)

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

使用taskkill选项时要记住的一件事是,除非您专门为它计划(也就是单例),否则您可能会运行多个Excel(或任何其他Office应用程序)副本,并无意中关闭了错误的实例

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

  

微软目前没有   推荐,不支持,   Microsoft Office自动化   任何无人看管的申请,   非交互式客户端应用程序或   组件(包括ASP,ASP.NET,   DCOM和NT Services),因为Office   可能表现出不稳定的行为和/或   在此运行Office时出现死锁   环境。

作为替代方案,有一种名为Aspose Cells的产品,它提供的产品旨在允许您以编程方式使用服务器环境中的Excel工作表。作为免责声明,我从未亲自使用过此产品,但我从过去与之合作过的几个人那里听说过它。

答案 2 :(得分:4)

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

开始使用代码构建office文档的一些好的链接。 http://msdn.microsoft.com/en-us/magazine/cc163478.aspx http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx

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

GC确实可以正常工作你没有正确使用它遵循这种模式...

   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在任务管理器中运行。在假设上述代码不起作用之前,请检查运行代码的进程是否也已关闭。对于VSTO或COM插件,检查Word / powerpoint /其他excel实例是否也已关闭,因为仍有GC根返回到启动过程。关闭后,Excel.exe进程将关闭。

答案 3 :(得分:3)

您使用的是VSTO吗?完成excelobject.Quit();后,您可以关闭Excel应用程序它对我有用,但我不再在服务器端使用Excel了。

您可以查看Excel的XML架构,以构建不含Excel本身的Excel文件。查看CarlosAg Excel Writer,它完全相同。

答案 4 :(得分:3)

我遇到了类似的问题。虽然'taskkill excel.exe'或枚举所有“excel”进程并杀死它们确实有效,但这会杀死所有正在运行的Excel进程。你最好只杀死你正在使用的实例。

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

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。

'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

这是找到正确进程的可靠方法,因为对于多个进程,BaseAddress有时似乎是相同的(导致杀死错误的PID)。

答案 5 :(得分:2)

您需要的命令是“taskkill”。

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

> taskkill excel.exe

答案 6 :(得分:2)

:)。我用Excel here记下了我的小冲突。它也有一些我经过一番搜索后发现的链接。希望它有所帮助。
基本上Excel是一种痛苦,即使它可以自动化。

答案 7 :(得分:1)

除了对mdb文件的数据访问外,我也不建议在服务器上使用Office应用程序。

我可以理解,有时候有必要。在这种情况下 我建议如下:

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

如果你绝对需要在同一台服务器上进行,那么至少在它自己的应用程序池中实现上述功能。

限制自己保留一个工作队列,只有一个Excel(或任何其他办公室应用程序)实例让你放弃使用TaskKill或.Kill()而不会失去工作。

我相信如果你将它保留在一个线程中,那么你很少需要杀死它。

答案 8 :(得分:1)

我已使用spreadsheetgear在服务器上生成XL报告,但效果非常好。我们不必担心EXCEL流程..

答案 9 :(得分:0)

结束工作后,您需要安全地处理所有COM互操作对象。 “all”我的意思是绝对所有:collections属性值,依此类推。我在设置过程中创建了堆栈对象并推送了对象:

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仍在那里你必须手动杀死它。

答案 10 :(得分:0)

我遇到了类似的问题并使用了以下代码:

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。

答案 11 :(得分:0)

我实际上有一个类似于此问题的问题 - Check for hung Office process when using Office Automation - 对该问题的一些回答可能对您有用。

另外,我必须同意其他人在保持任何Office产品不在服务器上的说法;但是,由于您正在使用Excel,因此生成Excel XML documents可能是可行的。您可以执行此操作而无需执行任何Office自动化,并且该过程非常简单。对于基于网格的简单电子表格,我发现它比使用Excel自动化它要容易一些。 Office Open XML功能非常强大,可以提供更复杂的报告以及更多功能。

答案 12 :(得分:0)

最好的方法是使用专门构建的库(例如Aspose中的库)来生成电子表格或填充模板。下一个最好的方法是根据您的需要使用xml格式的办公室。有时候适合的轻量级方法是创建一个HTML文件,其中包含一个表,并使用.xls扩展名命名。 Excel会很高兴地读到它,但它的功能非常有限。

这些是我用过的选项(但并不多)。还有一个名为Microsoft Office Sharepoint Server的东西,但我不知道它真正让你做多少。

那就是说,你的问题正在发生,因为当你调用常规的Excel库时,你实际上是完全独立于.Net旋转Excel,实际上只是使用代理库与它交谈。这与WCF和服务完全相同。您不会期望服务因为客户端应用程序使用它而死亡。更糟糕的是,Excel是一种非托管资源,根本不会被处理/完成/垃圾收集。 .Net Runtime不了解Excel,它只知道这些代理。 Application.quit就是您所需要的,您可能还需要显式释放所创建的com对象。

答案 13 :(得分:-1)

我在这个链接上找到了一个很棒的解决方案: http://www.antionline.com/showthread.php?t=277640

这对我有用。