代码之家  ›  专栏  ›  技术社区  ›  Codeslayer

正在删除服务器上的Excel.EXE[重复]

  •  11
  • Codeslayer  · 技术社区  · 16 年前

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

    假设一个ASP.NET web应用程序在服务器上生成自动的Excel报表。如何在处理结束后终止服务器端的Excel.EXE。我是有目的地提出这个问题的,因为我相信垃圾回收器不会清理Excel可执行文件,即使在Excel文件关闭之后。

    有什么建议会有帮助吗?

    14 回复  |  直到 7 年前
        1
  •  18
  •   Galwegian    16 年前

    很抱歉这么说,我不是想变得聪明,但是。。。 不要把office放在服务器上!!!

    如果我没听错的话!:)

    编辑: 即使我已经被降职了,我永远不会 曾经 提倡在服务器上运行Office-事实证明 也一样 过去对我来说是一种痛苦。

    说到这里,我和Crystal Reports也一样了;-)

        2
  •  6
  •   Jason Z    16 年前

    我同意不在服务器上运行Office。不是说我在这件事上有任何选择:)

    taskkill选项需要记住的一件事是,除非您特别计划它(aka-singleton),否则您可能有多个Excel(或任何其他Office应用程序)副本正在运行,并且无意中关闭了错误的实例。

    还要注意的是 http://support.microsoft.com/kb/257757

    微软目前没有 推荐,但不支持, 微软办公自动化 任何无人值守的应用程序, 非交互式客户端应用程序或 组件(包括ASP,ASP.NET, DCOM和NT服务),因为Office 可能表现出不稳定的行为和/或 在这种情况下运行Office时出现死锁 环境。

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

        3
  •  4
  •   Anonymous Type    14 年前

    我有更多的时间考虑这个答案,现在建议使用带有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的能力。 不要在服务器上运行office。把钱浪费在购物或电子表格上。

    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/other excel实例是否也已关闭,因为仍有GC根目录返回到启动过程。一旦关闭,Excel.exe进程将关闭。

        4
  •  3
  •   Biri    16 年前

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

    您可以查看Excel的XML模式来构建没有Excel本身的Excel文件。退房 CarlosAg Excel Writer ,其作用完全相同。

        5
  •  3
  •   Vincent Van Den Berghe    16 年前

    我也遇到过类似的问题。虽然'taskkill excel.exe'或枚举所有“excel”进程并终止它们确实有效,但这会终止所有正在运行的excel进程。你最好只杀掉你正在处理的实例。

    这是我用来实现这一点的代码。它使用了一种松饼(参见 here )从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
    

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

        6
  •  2
  •   Mark Ingram    16 年前

    你需要的命令是“taskkill”。

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

    > taskkill excel.exe
    
        7
  •  2
  •   Gishu    16 年前

    :). 我用Excel记下了我的小冲突 here . 它也有一些链接,我找到了一些经过仔细搜索。希望有帮助。
    基本上Excel是一种痛苦,尽管它可以自动化。

        8
  •  1
  •   bruceatk    16 年前

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

    我完全可以理解,有时候这是必要的。在thoses案例中 我建议如下:

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

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

    限制自己保持一个工作队列,并且只有一个Excel实例(或任何其他office应用程序)让我们放弃使用TaskKill或.kill()来终止它,而不丢失工作。

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

        9
  •  1
  •   MOZILLA    16 年前

    我用过 spreadsheetgear 在服务器上生成XL报告,它工作得非常好。我们不必担心EXCEL进程。。

        10
  •  0
  •   Fabian    16 年前

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

    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
  •   Community CDub    7 年前

    我刚才有个问题跟这个很相似- Check for hung Office process when using Office Automation -对这个问题的一些回答可能对你有用。

    另外,我必须同意其他人所说的关于让任何办公产品远离服务器的说法;但是,由于您正在使用Excel,因此生成 Excel XML documents . 您无需进行任何办公自动化就可以做到这一点,而且过程相当简单。对于简单的基于网格的电子表格,我发现它比使用Excel实现自动化要容易一些。这个 Office Open XML 是相当强大的,并允许更复杂的报告是可能的,以及一些更多的努力。

        12
  •  0
  •   Paul Sasik    14 年前

    结束工作后,您需要安全地释放所有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仍然存在,则必须手动终止它。

        13
  •  0
  •   Jim L    14 年前

    最好的方法是使用专门构建的库(如Aspose中的库)来生成电子表格或填充模板。下一个最好的方法是在您需要的时候使用office的xml格式。有时适合的轻量级方法是创建一个包含一个表的HTML文件,并使用.xls扩展名命名它。Excel很乐意阅读,但它所能做的却非常有限。

    这些是我使用过的选项(但不多)。还有一个叫做MicrosoftOfficeSharepointServer的东西,但我不知道它到底能让你做多少。

    也就是说,您的问题之所以会发生,是因为当您调用常规的Excel库时,实际上您正在完全独立于.Net旋转Excel,而实际上只是使用一个代理库与之交谈。这与WCF和服务的类型几乎相同。您不会仅仅因为客户机应用程序使用它而期望服务死亡。更糟糕的是,Excel是一个非托管资源,根本不会被处理/定稿/垃圾回收。.NET运行时不知道Excel,它只知道那些代理。Application.quit是您需要的,而且您可能需要显式释放创建的com对象。

        14
  •  -1
  •   stefano m    16 年前

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

    对我来说真的很管用。