2012-08-01 203 views
4

我的問題基本上就是如何結束使用excel時運行的Excel.exe進程。在應用程序中,我打開並使用一對Excel工作簿,然後讓用戶按照自己的意願去做,但問題是我的應用程序從未放棄過程。Excel進程在VB.net關閉後仍然運行

如果應用程序在關閉excel之前關閉,則在excel關閉時結束該過程,否則,如果在關閉excel後關閉應用程序,則該過程將保持運行。

我已經嘗試了一些我在互聯網上發現的與GC.collect相關的事情,並且正在等待未決的終結器或者沿着這些行發生的事情,但是都沒有奏效。

我也可以愉快地關閉excel過程,唯一的問題是不知道我是否關閉了一個用戶重要的電子表格,他們忽略了保存還是我的。

我不確定我的代碼是否有助於答案,但我正在使用microsoft.office.interop.excel獲取excel,並且我正在使用已保存在應用程序資源文件夾中的工作簿。

CNC中

這裏的一切,我已經試過了,我知道這是一個有點矯枉過正,但遺憾的是它仍然無法結束進程

Marshal.ReleaseComObject(FirstWorksheet) 
Marshal.FinalReleaseComObject(FirstWorksheet) 
Marshal.ReleaseComObject(SecondWorksheet) 
Marshal.FinalReleaseComObject(SecondWorksheet) 
Marshal.ReleaseComObject(ThirdWorksheet) 
Marshal.FinalReleaseComObject(ThirdWorksheet) 
Marshal.ReleaseComObject(FourthWorkSheet) 
Marshal.FinalReleaseComObject(FourthWorkSheet) 
Marshal.ReleaseComObject(xlRange) 
Marshal.FinalReleaseComObject(xlRange) 
Marshal.ReleaseComObject(SecondxlRange) 
Marshal.FinalReleaseComObject(SecondxlRange) 
Marshal.ReleaseComObject(thirdxlRange) 
Marshal.FinalReleaseComObject(thirdxlRange) 
Marshal.ReleaseComObject(fourthxlRange) 
Marshal.FinalReleaseComObject(fourthxlRange) 
Marshal.ReleaseComObject(.activeworkbook) 
Marshal.FinalReleaseComObject(.activeworkbook) 
Marshal.ReleaseComObject(excelApplication) 
Marshal.FinalReleaseComObject(excelApplication) 
MSExcelControl.QuitExcel() 'A function made by someone else I work with that was meant to close excel's process 
GC.Collect() 
GC.WaitForPendingFinalizers() 
GC.Collect() 
GC.WaitForPendingFinalizers() 

CNC中這裏的quitExcel方法

Friend Shared Sub QuitExcel() 
    If Not getExcelProcessID = -1 Then 
     If Not excelApp Is Nothing Then 
      'Close and quit 
      With excelApp 
       Try 
        Do Until .Workbooks.Count = 0 
         'Close all open documents without saving 
         .Workbooks(1).Close(SaveChanges:=0) 
        Loop 
       Catch exExcel As Exception 
        'Do nothing 
       End Try 
       Try 
        .ActiveWorkbook.Close(SaveChanges:=0) 
       Catch ex As Exception 
        'Do nothing 
       End Try 

       Try 
        .Quit() 
       Catch ex As Exception 
        'Do nothing 
       Finally 
        myExcelProcessID = -1 
       End Try 
      End With 
      excelApp = Nothing 
     End If 
    End If 
End Sub 

他已經嘗試在他的類中使用進程ID做同樣的事情,問題是他沒有工作,這就是爲什麼我試圖再次獲得進程ID本身, orked

+0

可能有興趣:http://stackoverflow.com/questions/1610743/reading-excel-files-in-vb-net-leaves-excel-process-hanging – Fionnuala 2012-08-01 14:26:16

+0

也可以在這裏看到:http:// stackoverflow。 com/questions/1041266/c-sharp-and-excel-automation-ending-the-running-instance/1041740#1041740 – sloth 2012-08-01 14:28:16

+0

謝謝,我會看看他們倆! – Alex 2012-08-01 14:29:18

回答

2

我前段時間有同樣的問題,請嘗試在您的Excel對象上使用Marshal.ReleaseComObject。它位於System.Runtime.InteropServices命名空間中。另外記得事先關閉你的excel對象。

xlWorkbook.Close(); 
xlApp.Close(); 
Marshal.ReleaseComObject(xlWorkbook); 
Marshal.ReleaseComObject(xlApp); 
+0

這就是我試過的,它仍然沒有工作:/ – Alex 2012-08-03 09:14:44

4

它採取了很長的時間,但我終於解決了它,做它是當你創建Excel應用程序來記錄進程ID的最佳方式,這意味着你知道有關聯的唯一ID的僅處理。

要做到這一點,我看着那些已經存在的所有進程,記錄在一組ID excel的進程的ID的

  msExcelProcesses = Process.GetProcessesByName("Excel") 
      'Get all currently running process Ids for Excel applications 
      If msExcelProcesses.Length > 0 Then 
       For i As Integer = 0 To msExcelProcesses.Length - 1 
        ReDim Preserve processIds(i) 
        processIds(i) = msExcelProcesses(i).Id 
       Next 
      End If 

然後重複上述過程,打開我的後直(嘗試和預防他們自己打開excel並擁有2個新的excel進程)記錄新的ID,檢查不在最後一個列表中的ID並將其存儲爲整數。

然後,所有你需要做底通過的進程列表循環,殺死一個與你的ID

   Dim obj1(1) As Process 
       obj1 = Process.GetProcessesByName("EXCEL") 
       For Each p As Process In obj1 
        If p.Id = MSExcelControl.getExcelProcessID Then 
         p.Kill() 
        End If 
       Next 
+0

我不認爲這是一個好主意。如果你乾脆退出Excel,這個過程應該自行退出。 – Enigmativity 2012-08-02 12:03:20

+0

它從來沒有做過? – Alex 2012-08-02 12:06:30

+5

@Enigmativity如果你可以幫助不僅僅是downvoting,並告訴我我已經試過的東西,然後我會很感激它 – Alex 2012-08-02 12:15:25

8

很好的解決亞歷克斯,我們不應該這樣做,但是我們做的,EXCEL不會結束。我採取了你的解決方案,並創建了下面的代碼,在我的應用程序導入或導出Excel之前,我打電話給ExcelProcessInit,然後在ExcelProcessKill完成後調用它。

Private mExcelProcesses() As Process 

Private Sub ExcelProcessInit() 
    Try 
    'Get all currently running process Ids for Excel applications 
    mExcelProcesses = Process.GetProcessesByName("Excel") 
    Catch ex As Exception 
    End Try 
End Sub 

Private Sub ExcelProcessKill() 
    Dim oProcesses() As Process 
    Dim bFound As Boolean 

    Try 
    'Get all currently running process Ids for Excel applications 
    oProcesses = Process.GetProcessesByName("Excel") 

    If oProcesses.Length > 0 Then 
     For i As Integer = 0 To oProcesses.Length - 1 
     bFound = False 

     For j As Integer = 0 To mExcelProcesses.Length - 1 
      If oProcesses(i).Id = mExcelProcesses(j).Id Then 
      bFound = True 
      Exit For 
      End If 
     Next 

     If Not bFound Then 
      oProcesses(i).Kill() 
     End If 
     Next 
    End If 
    Catch ex As Exception 
    End Try 
End Sub 

Private Sub MyFunction() 
    ExcelProcessInit() 
    ExportExcelData() 'Whatever code you write for this... 
    ExcelProcesKill() 
End Sub 
+0

這是非常感謝 – 2016-01-20 13:17:54

4

我知道這是一個古老的線程,但如果有人回來到這一點,你實際上有打電話給每一個Interop.Excel對象,你工作簿中的觸摸。如果你將一個實例化的類從Excel中拖入你的代碼中,那麼當你完成它時,Marshal.ReleaseComObject。甚至每個細胞。這很瘋狂,但這是我能夠解決相同問題的唯一方法。

並確保你沒有致命的異常,並留下未發佈的東西... Excel將保持打開狀態。

Excel.Applicaiton? Marshal.ReleaseComObject的。

Excel.Workbook? Marshal.ReleaseComObject的。

Excel.Workshet? Marshal.ReleaseComObject的。

Excell.Range? Marshal.ReleaseComObject的。

循環行? Marshal.ReleaseComObject你循環的每一行和單元格。

Exce.Style? Marshal.ReleaseComObject ...至少這是我必須做的...

如果您計劃使用PIA訪問Excel,請從您編寫的第一行代碼中計劃如何發佈你的對象。我所擁有的最佳方法是確保從Excel對象中提取excel值並將其加載到我自己的內部變量中。然後立刻打電話給你訪問的Marshal.ReleaseComObject。通過應用程序,工作簿,工作表,ListObject,表等中的列表循環訪問excel對象往往是最難發佈的。因此規劃相當關鍵。

相關問題