【问题标题】:Terminate All Remaining Excel Sessions, only created by Access VBA Procedure终止所有剩余的 Excel 会话,仅由 Access VBA 过程创建
【发布时间】:2018-08-03 17:01:33
【问题描述】:

有什么方法可以将 MS-Access VBA 创建的 EXCEL Session 与用户创建的其他 EXCEL Session 区分开来?

目前,我通过进程 ID 终止了 Excel 会话,在程序结束时明确地终止了它。 因为它们可以保留,即使该实例肯定会关闭。

为避免任何剩余的 Excel 会话,我想终止由 MS-Access VBA 创建的所有其他 Excel 会话,但不包括用户的 Excel 会话。

这里是当前脚本仅供您参考。我们可以通过#2 子过程终止所有的 excel 会话,但可以包含用户会话。

-- #1 检查进程 ID 并在过程结束时终止

Public Declare Function GetWindowThreadProcessId Lib "user32" _
  (ByVal hwnd As Long, ByRef lpdwProcessId As Long) As Long

'Create New Instance
Set objExcel = New Excel.Application

'Get ProcessID of Excel Instance, Opened in this procedure.
Dim ProcXLID
Dim CurrentThreadID

ProcXLID = 0
CurrentThreadID = GetWindowThreadProcessId(objExcel.hwnd, ProcXLID)
Debug.Print "Current Excel Instance Handle : " & objExcel.hwnd & " ProcessID : " & ProcXLID

~ Export Excel Reports ~

'Close instance
objExcel.Quit
Set objExcel = Nothing

'Terminate own Excel Session if remains
ExcelProcess_kill ProcXLID

--#2。程序终止 Excel 会话

Sub ExcelProcess_kill(ByVal ProcID As Integer)

On Error Resume Next

    Dim objProcList
    Dim objProcess

    Dim StrProcName
    StrProcName = "EXCEL.EXE"

    Dim SessionCnt As Long
    SessionCnt = 0

    Set objProcList = GetObject("winmgmts:").InstancesOf("win32_process")

    'For Named Excel Process -- ExcelProcess_kill(pid)
    If ProcID > 0 Then

        For Each objProcess In objProcList
            If LCase(objProcess.Name) = StrProcName And LCase(objProcess.ProcessID) = ProcID Then
                Debug.Print "Terminate Session Info."; objProcess.Name; objProcess.ProcessID
                objProcess.Terminate
                SessionCnt = SessionCnt + 1
            End If
        Next

    'For All Excel Process -- ExcelProcess_kill(0) 
    Else

        For Each objProcess In objProcList
            If LCase(objProcess.Name) = StrProcName Then
                Debug.Print "Terminate Session Info."; objProcess.Name; objProcess.ProcessID
                objProcess.Terminate
                SessionCnt = SessionCnt + 1
            End If
        Next

    End If

    Debug.Print "Terminated Session Cnt :" & SessionCnt

End Sub

任何建议将再次受到高度赞赏。

【问题讨论】:

  • 开放这么多会话的原因是什么?为什么不解决这个核心问题,而不是解决一个混乱的解决方案呢?您需要多个 Excel 实例的原因很少,而且多个实例也没有理由,因为多个工作簿可以在同一个实例中运行。
  • @ashleedawg,感谢您的评论。我已经修复了主要代码和剩余会话的可能性较小,它应该在正常结束和错误捕获部分被杀死。但是我仍然担心有可能,例如用户在此过程中关闭程序而不是错误的情况。

标签: excel ms-access session pid


【解决方案1】:

确定用户是否打开 Excel 应用程序的一种简单方法是使用 Application.UserControl 属性,该属性对于用户打开的应用程序为 true,但对于使用 VBA 打开的应用程序为 false。

您可以使用this answer 中的代码获取所有正在运行的 Excel 应用程序的应用程序对象列表。然后你可以使用你现有的代码杀死它们。

请注意,其他程序打开的 Excel 应用程序也会终止。无法区分哪个 COM 程序打开了 Excel 应用程序。

另请注意,使 Excel 应用程序可见会将此属性设置为 true。但这可能是需要的,因为用户可能会在您创建的可见应用程序实例中打开其他工作簿,而杀死这可能会导致用户丢失工作。

【讨论】:

  • 埃里克,再次感谢您提供的友好和有用的信息!这正是我想要的......!我会在我们自己的系统中验证它。
猜你喜欢
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多