2008-09-09 48 views
11

可能重複:
How to properly clean up Excel interop objects in C#服務器上殺EXCEL.EXE

假設一個ASP.NET Web應用程序自動生成服務器上的Excel報表。一旦處理結束,我們如何殺死服務器端Excel.EXE。我故意提出這個問題,因爲我相信即使在Excel文件關閉後,Garbage Collecter也不會清除Excel可執行文件。

任何指針會有幫助嗎?

+0

我剛剛在這裏回答了這個問題:[殺死excel進程的主窗口hWnd](http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects- in-c/1893653#1893653) – nightcoder 2009-12-12 14:55:48

回答

3

是否使用VSTO?完成後,您可以關閉Excel應用程序excelobject.Quit();它對我很有用,但我不再在服務器端使用Excel。

您可以看看Excel的XML架構來構建沒有Excel本身的Excel文件。看看CarlosAg Excel Writer,完全一樣。

18

不好意思地說這個,我並不是想要變聰明,但是...... 不要把辦公室放在服務器上!

這就是如果我理解正確! :)

編輯:儘管我已經下調了這一點,我永遠永遠倡導在服務器上運行Office - 它已被證明太多的屁股痛,我以往。

說了這麼多,同樣現在去爲我和Crystal Reports ;-)

+3

作爲一般原則我同意,但在現實世界中,有很多情況下Excel是業務的關鍵部分,許多業務流程都是圍繞它建立的。當這些需要縮放時,唯一的選擇通常是將Excel作爲服務器端組件運行。 – 2008-09-09 09:38:58

+0

別擔心,我們中的一些人投票贊成你:)我完全同意 - 運行Excel作爲某種數據處理器(服務器或客戶端)似乎瘋了。 Excel是一個(臃腫的)前端用戶應用程序,不應該用於後端處理。 – 2008-09-09 09:53:42

2

:)。我用Excel here記下了我的小衝突。它也有一些鏈接,我經過一番大量搜索後發現。希望能幫助到你。
基本上Excel是一種痛苦,即使它可以自動化。

0

在完成工作後,您需要安全地處理所有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仍然存在,你必須手動殺死它。

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(); 
    } 
} 

這工作得很好,但我真的想與辦公室的服務器上運行。

1

我也不會推薦在服務器上使用辦公應用程序,除了數據訪問mdb文件。

我完全可以理解有時候有必要。在案件 我會推薦以下內容:

  • 創建一個單獨的服務器,這是唯一的功能。 (讓我們以最小的影響重新啓動)。
  • 讓服務器執行請求排隊
  • 的機制,保持一個單獨的線程處理隊列中。這使您能夠跟蹤辦公應用程序,並在必要時將其終止,並繼續執行,而不會影響任何排隊的作業或其他應用程序。

如果你絕對需要在同一臺服務器上完成它,那麼至少應該在它自己的應用程序池中實現上述功能。

限制自己保持工作的隊列中,只有一個的Excel(或任何其他辦公應用程序)的實例讓你殺它與TASKKILL或.Kill()放棄並不會失去工作的。

我相信,如果你把它保存到一個單獨的線程,那麼你將很少有必要殺死它。

6

我同意在服務器上不運行Office。不是我在這件事情上有任何選擇:)

有一件事要記住taskkill選項,是除非你明確規劃它(又名 - 單身),你可能有多個副本的Excel(或任何其他Office應用程序)正在運行,並無意中關閉了錯誤的實例。

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

微軟目前不 建議,並且不支持, 自動化的Microsoft Office從任何無人值守, 非交互式客戶端應用程序 應用程序或 組件(包括ASP的,ASP.NET, DCOM和NT Service),因爲Office 當Office在這種環境 運行可能會出現不穩定的行爲和/或 僵局。

作爲替代,有一個叫做Aspose Cells產品,提供了設計,讓您以編程方式與Excel工作表在服務器環境中工作的產物。作爲一個免責聲明,我從未親自使用過這款產品,但我從過去曾與之合作過的幾個人那裏聽說過它。

0

其實我有一個問題,就是類似這樣的一段時間回來 - Check for hung Office process when using Office Automation - 一些答覆這個問題的可能是對您有用。

另外,我有什麼其他人都在問候保留任何Office產品關閉服務器的話說同意;但是,由於您正在使用Excel,因此您可以生成Excel XML documents。你可以做到這一點,而不必做任何Office自動化,這個過程非常簡單。對於簡單的基於網格的電子表格,我發現它比使用Excel自動化它更容易一些。 Office Open XML是相當強大的,並允許更復雜的報告,以及更多的努力。

3

我有過類似的問題。雖然'taskkill出色。exe「或枚舉所有」excel「進程並殺死它們都能正常工作,這會殺死所有正在運行的Excel進程。你最好只殺死你當前使用的實例。

以下是我用來完成該操作的代碼。它使用PInvoke(請參閱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 

這是不是可靠的方法來找到正確的過程中,由於BaseAddress有時似乎是幾個進程(導致殺錯PID)相同。

1

我已經使用spreadsheetgear在服務器上生成XL報告,它工作得很好。我們不必擔心EXCEL過程..

4

我已經有更多時間思考這個問題了,現在將推薦使用Open XML Office電子表格格式的XML方法。

繼承人一些很好的鏈接,開始構建與代碼的辦公文檔。 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進程將關閉。

0

最好的方法是使用專門構建的庫,例如Aspose的庫,以生成電子表格或填充模板。下一個最好的辦法是在辦公室使用xml格式,如果切合您的需要。有時適合的輕量級方法是創建一個帶有一個表格的HTML文件,並以.xls擴展名命名。 Excel會高興地閱讀它,但它的功能非常有限。

這些是我用過的選項(但不是很多)。還有一種叫做Microsoft Office Sharepoint Server的東西,但我不知道它真的可以讓你做多少事。

這就是說,你的問題發生了,因爲當你調用常規的Excel庫時,你實際上完全獨立於.Net而完全旋轉了Excel,實際上只是使用代理庫來與它交談。這幾乎與WCF和服務一樣。您不會期望該服務會因爲客戶端應用程序使用它而死亡。更糟的是,Excel是一個非託管資源,不會被處理/完成/垃圾收集。 .Net Runtime不知道Excel,只知道那些代理。 Application.quit是你需要的,你也可能需要明確地釋放創建的com對象。