退出后,Excel的VBA自动化在内存中留下一个进程

use*_*542 8 excel vba

我已经看到了很多关于这个问题的建议,我已经尝试了所有这些,但似乎都没有.VBA代码位于非Microsoft产品(SAP Business Objects,这可能是问题).我创建了一个Excel对象:

Set oExcel = CreateObject("Excel.Application")

从特定工作簿中的某个工作表的第1列加载内容,然后关闭Excel.每次,它在内存中留下一个进程,占用5+ mb的内存.

我尝试使oExcel对象可见,这样至少我可以在不使用任务管理器的情况下杀死它,但是当我调用Quit时,UI退出,仍然离开了进程.

每次运行代码时,它都会创建一个新进程.所以我尝试通过调用重用任何现有的Excel进程

Set m_oExcel = GetObject(, "Excel.Application")

并且只有在该调用不返回任何内容时才创建它

这并没有扩散这些过程,但单个过程每次增长5+ mb,因此问题基本相同.

在每种情况下,我关闭我打开的工作簿,并在退出之前将DisplayAlerts设置为False:

m_oBook.Close SaveChanges:=False
m_oExcel.DisplayAlerts = False
m_oExcel.Quit
Run Code Online (Sandbox Code Playgroud)

这段代码已经使用了至少五年,但是在我们迁移到Windows 7之前,这个问题并没有出现.

如果它有帮助,这是完整的代码.请注意,所有Excel对象都是每个建议的模块级变量("m_"前缀),并且我已根据另一个建议使用了"一点"规则.我也尝试使用通用对象(即后期绑定),但这也没有解决问题:

Private Function GetVariablesFromXLS(ByVal sFile As String) As Boolean
    On Error GoTo SubError

    If Dir(sFile) = "" Then
        MsgBox "File '" & sFile & "' does not exist.  " & _
               "The Agent and Account lists have not been updated."
    Else
        Set m_oExcel = CreateObject("Excel.Application")
        Set m_oBooks = m_oExcel.Workbooks
        Set m_oBook = m_oBooks.Open(sFile)

        ThisDocument.Variables("Agent(s)").Value = DelimitedList("Agents")
        ThisDocument.Variables("Account(s)").Value = DelimitedList("Accounts")
    End If

    GetVariablesFromXLS = True

SubExit:

    On Error GoTo ResumeNext
    m_oBook.Close SaveChanges:=False
    Set m_oBook = Nothing
    Set m_oBooks = Nothing

    m_oExcel.DisplayAlerts = False
    m_oExcel.Quit

    Set m_oExcel = Nothing

    Exit Function

SubError:
    MsgBox Err.Description
    GetVariablesFromXLS = False
    Resume SubExit

ResumeNext:
    MsgBox Err.Description
    GetVariablesFromXLS = False
    Resume Next

End Function
Run Code Online (Sandbox Code Playgroud)

Uri*_*ren 0

虽然这种情况不应该发生,但您可以向 Excel 发送“WindowClose”消息以强制关闭。

您将需要这些 API 函数

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Run Code Online (Sandbox Code Playgroud)

它应该看起来像这样:

// First, get the handle
hWindow = FindWindow(vbNullString, "Excel")
//Get proccess ID
GetWindowThreadProcessId(hWindow, ProcessValueID)
//Kill the process
ProcessValue = OpenProcess(PROCESS_ALL_ACCESS, CLng(0), ProcessValueID)
TerminateProcess(ProcessValue, CLng(0))
CloseHandle ProcessValueID
Run Code Online (Sandbox Code Playgroud)