使用Application.Quit后,Excel.exe仍在运行



我正试图通过编写检查Excel工作簿并填写Word文档的VBA代码来简化报告模板。

在任务管理器中终止Excel.exe进程失败。

我尝试了这里、其他论坛和微软文档中提出的解决方案。我认为这与运行应用程序时仍然存在的COM对象有关。退出方法,但不知道这些是从哪里来的

当将代码减少到最基本的组件时,任务管理器中仍然没有Excel.exe进程:

Private Sub Hämta_Click()
Dim XL As Excel.Application
Set XL = New Excel.Application
XL.Quit
Set XL = Nothing
End Sub

但是只要我添加到它,Excel.exe保持在任务管理器中运行:

Private Sub Hämta_Click()
Dim XL As Excel.Application
Set XL = New Excel.Application
Dim wkb As Excel.Workbook
Set wkb = XL.Workbooks.Open("C:Example.xls")
wkb.Close (False)
Set wkb = Nothing
XL.Quit
Set XL = Nothing
End Sub

我也尝试了这段代码,得到了相同的结果:

Private Sub Hämta_Click()
Dim XL As Object
Set XL = CreateObject("Excel.Application")
Dim wkb As Object
Set wkb = XL.Workbooks.Open("K:Uppdrag.xls")
wkb.Close (False)
Set wkb = Nothing
XL.Quit
Set XL = Nothing
End Sub

以上两个宏一直在创建未关闭的Excel.exe实例。

我已经看到了一些例子,其中包含的代码片段通过任务管理器杀死进程,但我不明白上面不起作用的原因。

我发现的唯一解决方法是不包括XL.Quit方法,而是设置XL.Visible = True,并让用户手动关闭窗口。

根据注释,似乎不可能找到新创建的excel实例不能在"正常"中完成的根本原因。方式。

根据这里的代码,可以直接终止进程

Option Explicit
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Type LUID
LowPart As Long
HighPart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
pLuid As LUID
Attributes As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
TheLuid As LUID
Attributes As Long
End Type
Function ProcessTerminate(Optional lProcessID As Long, Optional lHwndWindow As Long) As Boolean
Dim lhwndProcess As Long
Dim lExitCode As Long
Dim lRetVal As Long
Dim lhThisProc As Long
Dim lhTokenHandle As Long
Dim tLuid As LUID
Dim tTokenPriv As TOKEN_PRIVILEGES, tTokenPrivNew As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long

Const PROCESS_ALL_ACCESS = &H1F0FFF, PROCESS_TERMINATE = &H1
Const ANYSIZE_ARRAY = 1, TOKEN_ADJUST_PRIVILEGES = &H20
Const TOKEN_QUERY = &H8, SE_DEBUG_NAME As String = "SeDebugPrivilege"
Const SE_PRIVILEGE_ENABLED = &H2
On Error Resume Next
If lHwndWindow Then
'Get the process ID from the window handle
lRetVal = GetWindowThreadProcessId(lHwndWindow, lProcessID)
End If

If lProcessID Then
'Give Kill permissions to this process
lhThisProc = GetCurrentProcess

OpenProcessToken lhThisProc, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, lhTokenHandle
LookupPrivilegeValue "", SE_DEBUG_NAME, tLuid
'Set the number of privileges to be change
tTokenPriv.PrivilegeCount = 1
tTokenPriv.TheLuid = tLuid
tTokenPriv.Attributes = SE_PRIVILEGE_ENABLED
'Enable the kill privilege in the access token of this process
AdjustTokenPrivileges lhTokenHandle, False, tTokenPriv, Len(tTokenPrivNew), tTokenPrivNew, lBufferNeeded
'Open the process to kill
lhwndProcess = OpenProcess(PROCESS_TERMINATE, 0, lProcessID)

If lhwndProcess Then
'Obtained process handle, kill the process
ProcessTerminate = CBool(TerminateProcess(lhwndProcess, lExitCode))
Call CloseHandle(lhwndProcess)
End If
End If
On Error GoTo 0
End Function

你只需使用这样的代码

Sub TestIt()
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")

' Do something with xlApp


'Terminate the process
ProcessTerminate , xlApp.hwnd
End Sub

尝试声明和使用工作簿变量,然后将其设置为nothing在代码末尾

最新更新