【问题标题】:How to end excel.exe process?如何结束excel.exe进程?
【发布时间】:2011-07-08 13:04:01
【问题描述】:

我正在尝试从 vb.net 3.5 获取 excel 文件的 excel 工作表名称,但是它会打开,但 excel.exe 仍在处理中。如何在不从任务管理器中杀死 excel.exe 的情况下停止进程?

我意识到新的 excel.application 开始新的进程。

我尝试使用退出、关闭和处置............没有任何效果

下面是我的代码

   Dim sheetName As New Excel.XlSheetType
   Dim newExcell As New Excel.Application
   Dim newWorkBook As Excel.Workbook = app.Workbooks.Open(MyFileName)
   Dim worksheetName As String
   Dim ws As Excel.Worksheet = CType(WB.Worksheets.Item(1), Excel.Worksheet)
    worksheetName = ws.Name

我不能使用 kill 因为还有其他 excel 应用程序正在运行,所以我如何从处理器中关闭这个特定的 excel.exe。请帮忙

【问题讨论】:

标签: .net vb.net excel .net-3.5


【解决方案1】:

This KB article 描述了问题。

但是,这不是一个容易解决的问题,因为您必须确保在您实例化的每个 Excel 对象上调用 Marshal.ReleaseComObject - 而且很容易错过一个。

例如,以下代码隐式引用了一个 Workbooks 对象:

Dim newWorkBook As Excel.Workbook = app.Workbooks.Open(MyFileName) 

要释放 Workbooks 对象,您需要显式地引用它,以便您拥有一个可以调用 Marshal.ReleaseComObject 的引用:

Dim objWorkbooks As Excel.Workbooks = app.Workbooks
Dim newWorkbook As Excel.Workbook = objWorkbooks.Open(MyFileName)
...
Marshal.ReleaseComObject(objWorkbooks)
Marshal.ReleaseComObject(newWorkbook)
...

您还应该使用 Try/Finally 来确保即使抛出异常也会调用 ReleaseComObject。

【讨论】:

    【解决方案2】:

    很多人不建议杀掉进程;看 How to properly clean up Excel interop objectsUnderstanding Garbage Collection in .net

    编辑:另一方面,很多人不推荐使用 GC.Collect。见What's so wrong about using GC.Collect()?

    根据我的经验,终止进程是最快和最简单的。此代码仅杀死它启动的确切进程,不会杀死其他进程。

    确保关闭所有打开的工作簿,退出应用程序,释放 xlApp 对象。最后检查进程是否还活着,如果还活着,就杀死它。

    这是我使用的代码:(每次都有效)

    Sub UsingExcel()
    
        'declare process; will be used later to attach the Excel process
        Dim XLProc As Process
    
        'call the sub that will do some work with Excel
        'calling Excel in a separate routine will ensure that it is 
        'out of scope when calling GC.Collect
        'this works better especially in debug mode
        DoOfficeWork(XLProc)
    
        'Do garbage collection to release the COM pointers
        'http://support.microsoft.com/kb/317109
        GC.Collect()
        GC.WaitForPendingFinalizers()
    
        'I prefer to have two parachutes when dealing with the Excel process
        'this is the last answer if garbage collection were to fail
        If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then
            XLProc.Kill()
        End If
    
    End Sub
    
    'http://msdn.microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx
    <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
        ByRef lpdwProcessId As Integer) As Integer
    End Function
    
    Private Sub ExcelWork(ByRef XLProc As Process)
    
        'start the application using late binding
        Dim xlApp As Object = CreateObject("Excel.Application")
    
        'or use early binding
        'Dim xlApp As Microsoft.Office.Interop.Excel
    
        'get the window handle
        Dim xlHWND As Integer = xlApp.hwnd
    
        'this will have the process ID after call to GetWindowThreadProcessId
        Dim ProcIdXL As Integer = 0
    
        'get the process ID
        GetWindowThreadProcessId(xlHWND, ProcIdXL)
    
        'get the process
        XLProc = Process.GetProcessById(ProcIdXL)
    
    
        'do some work with Excel here using xlApp
    
        'be sure to save and close all workbooks when done
    
        'release all objects used (except xlApp) using NAR(x)
    
    
        'Quit Excel 
        xlApp.quit()
    
        'Release
        NAR(xlApp)
    
    End Sub
    
    Private Sub NAR(ByVal o As Object)
        'http://support.microsoft.com/kb/317109
        Try
            While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
            End While
        Catch
        Finally
            o = Nothing
        End Try
    End Sub
    

    【讨论】:

    • 是的。根据我的经验,我也必须这样做。但我会说,我会先尝试退出。然后我尝试检测周围是否有任何孤立的 Excel 进程(意味着必须跟踪由我自己的应用程序生成的 Excel 进程 ID)。
    • @code4life 我同意;我想你会注意到我的代码正是这样做的:退出,释放,如果没有退出,则杀死。
    【解决方案3】:

    使用 excel 应用程序对象。致电Quit()

    喜欢例如:

    Dim app As New Excel.Application    
    Try
        '...
        'After doing your stuff
        '...
        app.Quit()
    Catch ex As Exception
        'Log your exception
        System.Diagnostics.Print("Error: " + ex.Message)
    End Try
    

    【讨论】:

    • 我在严格依赖此调用时遇到了问题。特别是如果 Excel 在服务器进程上运行,则很有可能最终会出现一个或多个孤立的 Excel 进程。最好补充一种方法来杀死孤立的进程(这意味着跟踪 Excel 进程的进程 ID)。
    • @code4life 根据我的经验,当出现异常时会发生这种情况,最终导致不调用该例程。我建议您将逻辑包装在 try-catch-finally 结构中,并在 finally 块中调用 Quit()
    • OP 说“我尝试使用退出、关闭和处置............没有任何效果”
    • @code4life 调试时是否放置了断点并验证您上面提到的所有方法是否已实际执行...即断点是否在这些行处激活?
    • 是的,我认为在某些情况下 app.Quit() 会导致抛出异常或者它实际上并没有退出进程。这就是孤儿进程最终发生的原因。但这是在服务器应用程序上。但是,即使是边缘情况,仍然值得考虑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 2011-12-16
    • 2013-02-06
    • 2015-10-25
    • 1970-01-01
    • 2016-08-04
    • 2015-08-07
    相关资源
    最近更新 更多