在服务器上杀死Excel.EXE

时间:2020-03-05 18:49:54  来源:igfitidea点击:
Possible Duplicate:

  How to properly clean up Excel interop objects in C#

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

任何指针会有所帮助吗?

解决方案

回答

我们需要的命令是" taskkill"。

http://technet.microsoft.com/zh-CN/library/bb491009.aspx

> taskkill excel.exe

回答

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

我们可以查看Excel的XML模式来构建没有Excel本身的Excel文件。检查一下CarlosAg Excel Writer,它的功能完全相同。

回答

抱歉,我并不想变得聪明,但是...不要在服务器上放办公室!!!

那是我理解正确的地方! :)

编辑:即使我为此被打下了烙印,但我永远也不会提倡在服务器上运行Office,这在过去已证明对我来说太过痛苦。

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

回答

:)。我在这里用Excel记下了小冲突。它也有一些经过大量搜索后发现的链接。希望能帮助到你。
基本上,即使可以自动执行,Excel还是很麻烦的。

回答

结束工作后,我们需要安全地处置所有COM互操作对象。 "全部"是指绝对所有:集合属性值,依此类推。我已经创建了堆栈对象并在设置过程中推送了对象:

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仍然存在,则必须手动将其杀死。

回答

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

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。

回答

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

我绝对可以理解,有时候有必要。在那种情况下
我建议以下内容:

  • 创建一个单独的服务器,这是唯一的功能。 (让我们以最小的影响重新启动)。
  • 让服务器实现请求排队机制
  • 保持一个线程处理队列。这使我们能够跟踪Office应用程序,在必要时将其杀死,然后继续运行而不会影响排队的工作或者其他应用程序。

如果我们绝对需要在同一台服务器上执行此操作,则至少在其自己的应用程序池中实现以上内容。

限制自己排长队,只有一个Excel实例(或者任何其他Office应用程序),让我们放弃使用TaskKill或者.Kill()杀死它,而不丢失工作。

我相信,如果将其保留在单个线程中,则几乎不需要杀死它。

回答

我同意不在服务器上运行Office。并不是说我对此有任何选择:)

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

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

Microsoft does not currently
  recommend, and does not support,
  Automation of Microsoft Office
  applications from any unattended,
  non-interactive client application or
  component (including ASP, ASP.NET,
  DCOM, and NT Services), because Office
  may exhibit unstable behavior and/or
  deadlock when Office is run in this
  environment.

另外,还有一种名为Aspose Cells的产品,该产品提供的产品旨在使我们可以在服务器环境中以编程方式使用Excel工作表。作为免责声明,我从来没有亲自使用过该产品,但是我从过去与之共事的几个人那里听说过。

回答

我实际上有一个与此类似的问题,在使用Office Automation时检查挂起的Office进程,对该问题的某些答案可能对我们有用。

另外,对于将任何Office产品都保留在服务器之外,我必须同意其他所有人的说法;但是,由于我们正在使用Excel,因此生成Excel XML文档可能是可行的。我们可以执行此操作而不必执行任何Office自动化操作,并且此过程非常简单。对于简单的基于网格的电子表格,我发现它比尝试使用Excel自动化要容易一些。 Office Open XML功能非常强大,它允许进行更复杂的报告,也需要付出更多努力。

回答

我有一个类似的问题。尽管'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进行比较来找到正确的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)。

回答

我已经使用电子表格工具在服务器上生成XL报告,并且效果很好。我们不必担心EXCEL流程。

回答

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

这真的对我有用。

回答

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

这里有一些很好的链接,可以开始使用代码构建Office文档。
http://msdn.microsoft.com/zh-CN/magazine/cc163478.aspx
http://msdn.microsoft.com/zh-cn/library/bb735940(office.12).aspx

只需在SQL Server上使用SSIS。它提供了导出到Excel的功能。
不要在服务器上运行办公室。或者浪费金钱在aspose或者电子表格齿轮上。

GC确实可以正常工作,只是我们没有正确使用它就遵循此模式...

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

获取Excel操作类以实现IDisposable,然后将killExcel()保留在Dispose方法中。

更新:还请注意,有时开发人员仍会看到任务管理器中正在运行Excel.exe。在假定上述代码不起作用之前,请检查运行该代码的进程是否也已关闭。如果是VSTO或者COM加载项,请检查Word / powerpoint /其他excel实例是否也已关闭,因为仍有GC根目录可以返回启动过程。一旦关闭,Excel.exe进程将关闭。

回答

最好的方法是使用专用库(例如Aspose的库)来生成电子表格或者填充模板。第二种最佳方法是根据需要使用xml格式的Office。一种有时很合适的轻量方法是创建一个包含一个表的HTML文件,并以.xls扩展名命名。 Excel会很高兴地阅读到它,但是它只能做些有限的事情。

这些是我使用过的选项(但不多)。还有一个叫做Microsoft Office Sharepoint Server的东西,但我不知道它到底能为我们提供多少服务。

就是说,问题之所以发生是因为,当我们调用常规的Excel库时,实际上实际上是在完全独立于.Net的情况下扩展了Excel,实际上只是与代理库进行通讯。这几乎与我们使用WCF和服务所拥有的相同。我们不会期望该服务会因为客户端应用程序已使用它而消失。更糟糕的是,Excel是一种不受管理的资源,根本不会被处置/最终确定/垃圾收集。 .Net运行时不了解Excel,只了解那些代理。 Application.quit是我们所需要的,并且我们可能还需要显式释放创建的com对象。