4

使用 microsoft.office.interop.excel 关闭 Excel 以释放范围、工作表和工作簿不会关闭 Windows 中的进程。

我可以完全关闭所有 excel 实例,但不知道用户是否同时运行另一个 excel 实例。

这是我尝试过的一切

Marshal.ReleaseComObject(myWorksheet)
Marshal.FinalReleaseComObject(myWorksheet)
Marshal.ReleaseComObject(xlRange)
Marshal.FinalReleaseComObject(xlRange)
Marshal.ReleaseComObject(.activeworkbook)
Marshal.FinalReleaseComObject(.activeworkbook)
Marshal.ReleaseComObject(excelApplication)
Marshal.FinalReleaseComObject(excelApplication)
MSExcelControl.QuitExcel()
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

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
4

4 回答 4

10

好的解决方案亚历克斯,我们不应该这样做,但我们这样做了,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
于 2012-11-23T20:02:08.667 回答
4

我知道这是一个旧线程,但如果有人回到这个问题,您实际上必须调用您在工作簿中触摸的每个 Interop.Excel 对象。如果你从 Excel 中将一个实例化的类拉入你的代码,当你完成它时,Marshal.ReleaseComObject。甚至每一个细胞。这很疯狂,但这是我能够解决相同问题的唯一方法。

并确保您没有致命异常并留下未发布的内容...... Excel 将保持打开状态。

Excel.应用程序?Marshal.ReleaseComObject。

Excel.Workbook?Marshal.ReleaseComObject。

Excel.工作表?Marshal.ReleaseComObject。

Excell.Range?Marshal.ReleaseComObject。

循环遍历行?Marshal.ReleaseComObject 您循环遍历的每一行和单元格。

超风格?Marshal.ReleaseComObject...至少这是我必须做的...

如果您计划使用 PIA 访问 Excel,从您编写的第一行代码开始,计划您将如何发布您的对象。我拥有的最佳方法是确保从 Excel 对象中提取一个 excel 值并将其加载到我自己的内部变量中。然后立即调用您访问的 Marshal.ReleaseComObject。通过应用程序、工作簿、工作表、ListObject、表格等中的列表循环遍历 excel 对象往往是最难发布的。因此,计划是相当关键的。

于 2014-01-31T01:39:02.663 回答
4

当您打开excel并随后使用相同的PID关闭它时,我发现了一个粗略的工作来获取进程ID(PID)

在打开之前获取所有 excel 进程(以防另一个已经在运行):

            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后直接重复这个过程,新的PID应该是你的

然后你最后需要做的就是再次迭代列表并用你的 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
于 2012-08-02T11:59:42.633 回答
3

前段时间我遇到了同样的问题,尝试在你的 excel 对象上使用 Marshal.ReleaseComObject 。它位于 System.Runtime.InteropServices 命名空间中。还记得事先关闭你的 excel 对象。

xlWorkbook.Close();
xlApp.Close();
Marshal.ReleaseComObject(xlWorkbook);
Marshal.ReleaseComObject(xlApp);
于 2012-08-01T15:08:20.463 回答