可能重複:
How to properly clean up Excel interop objects in C#服務器上殺EXCEL.EXE
假設一個ASP.NET Web應用程序自動生成服務器上的Excel報表。一旦處理結束,我們如何殺死服務器端Excel.EXE。我故意提出這個問題,因爲我相信即使在Excel文件關閉後,Garbage Collecter也不會清除Excel可執行文件。
任何指針會有幫助嗎?
可能重複:
How to properly clean up Excel interop objects in C#服務器上殺EXCEL.EXE
假設一個ASP.NET Web應用程序自動生成服務器上的Excel報表。一旦處理結束,我們如何殺死服務器端Excel.EXE。我故意提出這個問題,因爲我相信即使在Excel文件關閉後,Garbage Collecter也不會清除Excel可執行文件。
任何指針會有幫助嗎?
我剛剛在VB.Net中試過這個,它能正常工作 System.Diagnostics.Process.Start(「taskkill.exe」,「-im excel.exe/f」) – JonnyGold 2008-09-09 12:04:43
是否使用VSTO?完成後,您可以關閉Excel應用程序excelobject.Quit();
它對我很有用,但我不再在服務器端使用Excel。
您可以看看Excel的XML架構來構建沒有Excel本身的Excel文件。看看CarlosAg Excel Writer,完全一樣。
不好意思地說這個,我並不是想要變聰明,但是...... 不要把辦公室放在服務器上!
這就是如果我理解正確! :)
編輯:儘管我已經下調了這一點,我永遠永遠倡導在服務器上運行Office - 它已被證明太太多的屁股痛,我以往。
說了這麼多,同樣現在去爲我和Crystal Reports ;-)
作爲一般原則我同意,但在現實世界中,有很多情況下Excel是業務的關鍵部分,許多業務流程都是圍繞它建立的。當這些需要縮放時,唯一的選擇通常是將Excel作爲服務器端組件運行。 – 2008-09-09 09:38:58
別擔心,我們中的一些人投票贊成你:)我完全同意 - 運行Excel作爲某種數據處理器(服務器或客戶端)似乎瘋了。 Excel是一個(臃腫的)前端用戶應用程序,不應該用於後端處理。 – 2008-09-09 09:53:42
:)。我用Excel here記下了我的小衝突。它也有一些鏈接,我經過一番大量搜索後發現。希望能幫助到你。
基本上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();
}
}
這工作得很好,但我真的想與辦公室的服務器上運行。
我也不會推薦在服務器上使用辦公應用程序,除了數據訪問mdb文件。
我完全可以理解有時候有必要。在案件 我會推薦以下內容:
如果你絕對需要在同一臺服務器上完成它,那麼至少應該在它自己的應用程序池中實現上述功能。
限制自己保持工作的隊列中,只有一個的Excel(或任何其他辦公應用程序)的實例讓你殺它與TASKKILL或.Kill()放棄並不會失去工作的。
我相信,如果你把它保存到一個單獨的線程,那麼你將很少有必要殺死它。
我同意在服務器上不運行Office。不是我在這件事情上有任何選擇:)
有一件事要記住taskkill選項,是除非你明確規劃它(又名 - 單身),你可能有多個副本的Excel(或任何其他Office應用程序)正在運行,並無意中關閉了錯誤的實例。
還要注意的是每http://support.microsoft.com/kb/257757
微軟目前不 建議,並且不支持, 自動化的Microsoft Office從任何無人值守, 非交互式客戶端應用程序 應用程序或 組件(包括ASP的,ASP.NET, DCOM和NT Service),因爲Office 當Office在這種環境 運行可能會出現不穩定的行爲和/或 僵局。
作爲替代,有一個叫做Aspose Cells產品,提供了設計,讓您以編程方式與Excel工作表在服務器環境中工作的產物。作爲一個免責聲明,我從未親自使用過這款產品,但我從過去曾與之合作過的幾個人那裏聽說過它。
其實我有一個問題,就是類似這樣的一段時間回來 - Check for hung Office process when using Office Automation - 一些答覆這個問題的可能是對您有用。
另外,我有什麼其他人都在問候保留任何Office產品關閉服務器的話說同意;但是,由於您正在使用Excel,因此您可以生成Excel XML documents。你可以做到這一點,而不必做任何Office自動化,這個過程非常簡單。對於簡單的基於網格的電子表格,我發現它比使用Excel自動化它更容易一些。 Office Open XML是相當強大的,並允許更復雜的報告,以及更多的努力。
我有過類似的問題。雖然'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)相同。
我已經使用spreadsheetgear在服務器上生成XL報告,它工作得很好。我們不必擔心EXCEL過程..
我發現這個鏈接上妙解: http://www.antionline.com/showthread.php?t=277640
它確實爲我工作。
我已經有更多時間思考這個問題了,現在將推薦使用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進程將關閉。
最好的方法是使用專門構建的庫,例如Aspose的庫,以生成電子表格或填充模板。下一個最好的辦法是在辦公室使用xml格式,如果切合您的需要。有時適合的輕量級方法是創建一個帶有一個表格的HTML文件,並以.xls擴展名命名。 Excel會高興地閱讀它,但它的功能非常有限。
這些是我用過的選項(但不是很多)。還有一種叫做Microsoft Office Sharepoint Server的東西,但我不知道它真的可以讓你做多少事。
這就是說,你的問題發生了,因爲當你調用常規的Excel庫時,你實際上完全獨立於.Net而完全旋轉了Excel,實際上只是使用代理庫來與它交談。這幾乎與WCF和服務一樣。您不會期望該服務會因爲客戶端應用程序使用它而死亡。更糟的是,Excel是一個非託管資源,不會被處理/完成/垃圾收集。 .Net Runtime不知道Excel,只知道那些代理。 Application.quit是你需要的,你也可能需要明確地釋放創建的com對象。
我剛剛在這裏回答了這個問題:[殺死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