VB.Net Office Interop - Excel进程未关闭

6ioyuze2  于 2023-05-19  发布在  .NET
关注(0)|答案(5)|浏览(243)

使用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
ovfsdjhp

ovfsdjhp1#

很好的解决方案亚历克斯,我们不应该这样做,但我们做了,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
0ejtzxu1

0ejtzxu12#

我知道这是一个老线程,但是如果有人回到这个问题,实际上你必须调用你在工作簿中接触到的每个Interop.Excel对象。如果从Excel中将示例化的类拉入代码中,当您完成它时,Marshal.ReleaseComObject。甚至每个细胞。这很疯狂,但这是我唯一能解决同样问题的方法。
并确保你没有一个致命的例外和留下一些未释放的东西... Excel将保持开放。
Excel.Applicaiton?Marshal.ReleaseComObject.
Excel.Workbook?Marshal.ReleaseComObject.
Excel.Workshet?Marshal.ReleaseComObject.
Excell.Range?Marshal.ReleaseComObject.
通过行循环?对循环遍历的每一行和单元格进行释放。
Exce.Style?Marshal.ReleaseComObject...至少这是我不得不做的...
如果您计划使用PIA访问Excel,那么从编写的第一行代码开始,就计划如何释放对象。最好的方法是确保从Excel对象中提取Excel值并将其加载到我自己的内部变量中。然后调用您访问的Marshal.ReleaseComObject。通过应用程序、工作簿、工作表、列表对象、表等中的列表遍历Excel对象往往是最难发布的。因此,规划相当关键。

i34xakig

i34xakig3#

我发现了一个粗略的工作,以获得进程ID(PID),当您打开Excel和关闭它使用相同的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***应该***是您的
最后你需要做的就是再次迭代list,并杀死那个有你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
nnt7mjpx

nnt7mjpx4#

不久前我也遇到了同样的问题,试着在你的excel对象上使用marshal.releasecomobject。它位于System.Runtime.InteropServices命名空间中。另外,请记住提前关闭Excel对象。

xlWorkbook.Close();
xlApp.Close();
Marshal.ReleaseComObject(xlWorkbook);
Marshal.ReleaseComObject(xlApp);
fkaflof6

fkaflof65#

不久前我遇到了这个。我需要修复路径中包含空格的错误,打开MS Excel并在每次关闭时成功关闭它。下面的代码为我工作。希望这能帮上忙。

Sub Main(ByVal CmdArgs() As String)

'path with spaces with cause errors
Dim DestinPath As String = "D:\ReflexCosting Ver.2\Excel\Order.xlsx"

Dim TAProcess1 As New Process

TAProcess1.StartInfo.FileName = "EXCEL.EXE"
TAProcess1.StartInfo.UseShellExecute = True
TAProcess1.StartInfo.Arguments = " """ & DestinPath & """"
TAProcess1.StartInfo.WorkingDirectory = " """ & DestinPath & """"
TAProcess1.StartInfo.WindowStyle = ProcessWindowStyle.Normal

AddHandler TAProcess1.Exited, New EventHandler(AddressOf p_Exited)

TAProcess1.EnableRaisingEvents = TAProcess1.Start()
TAProcess1.WaitForExit()

End Sub

'Called on Process exit "Will close any process started
Private Sub p_Exited(ByVal sender As Object, ByVal e As EventArgs)
Try
    ' remove the event
    RemoveHandler DirectCast(sender, Process).Exited, New EventHandler(AddressOf p_Exited)
    Console.WriteLine("Process has exited.")

Catch ex As Exception
    MsgBox(ex.Message, MsgBoxStyle.Critical, "Error: 09112")
End Try

End Sub

相关问题