【问题标题】:VBA FreeLibrary doesn't unload DLLVBA FreeLibrary 不卸载 DLL
【发布时间】:2017-08-16 19:23:22
【问题描述】:

我需要在使用完 DLL 文件后删除它(代码完成后清理)。

我尝试在 Excel VBA 中使用“LoadLibrary”和“FreeLibrary”,但无论我做什么,Excel.exe 都会紧贴 DLL 文件。

 Public Declare PtrSafe Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
 Public Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long

 Private Sub Load_Unload_DLL()

     Dim lb As Long, pa As Long
     lb = LoadLibrary("C:\Users\Administrator\Documents\MathLibrary.dll")

     'MsgBox "Library address: " & lb

     Dim FreeResult As Long
     FreeResult = 1

     Do Until FreeResult = 0
         FreeResult = FreeLibrary(lb)
     Loop

     Name "C:\Users\Administrator\Documents\MathLibrary.dll" As "C:\Users\Administrator\Documents\MathLibrary2.dll"

     Kill ("C:\Users\Administrator\Documents\MathLibrary2.dll")

 End Sub

尽管“FreeResult”等于“0”,但我在执行“Kill”命令时收到以下错误:

进程资源管理器显示 DLL 文件确实仍由 Excel 加载:

文件可以重命名,但不能删除(如代码所示)。

我错过了什么吗?

【问题讨论】:

  • FreeLib 只是减少引用计数。检查 FreeLib 返回值。如果它不为零,那么您实际上还没有卸载它。
  • @cyboashu 谢谢!我已经对此进行了测试,并更新了我的代码来解决这个问题。即使 FreeLib 返回 0 我仍然遇到错误。
  • 我不推荐使用 FreeLibrary 的循环。我试过在有和没有GetModuleHandle 的情况下这样做,但它有点不稳定。更多详情here

标签: excel vba dll delete-file


【解决方案1】:

我刚刚重新发现了这个答案,并且凭借更多经验建议不要使用它。

见:https://stackoverflow.com/a/28745693/3451115

我在使用这种方法时遇到的一个问题是,尽管库已被释放,但尝试重新加载它会使主机崩溃(对我来说是 MS Word)。

尽管它是邪恶的,但它可能会满足需要,因此请谨慎使用。


根据您的问题的根本原因,这可能会或可能不会有帮助,但我认为这是朝着正确方向迈出的一步。

FreeLib 的返回值 0 表示出现错误,而不是库已被释放,请参见此处:https://msdn.microsoft.com/en-us/library/windows/desktop/ms683152%28v=vs.85%29.aspx

据我了解,FreeLib 的调用次数应与使用 LoadLibrary 的次数一样多……因此,与其循环直到出现错误 (FreeLib = 0),不如使用一个循环来释放库,然后检查是否该库仍在加载中,请尝试以下操作:

    Do Until lb = 0
        FreeLibrary lb
        If CBool(Err.LastDllError) Then
            debug.print "dll error" & " " & Err.LastDllError
            Err.Clear
            Exit Do
        End If

        lb = 0 ' Reset lb needed for test on next line

        ' Check if the dll really has been released...
        lb = GetModuleHandle("C:\Users\Administrator\Documents\MathLibrary.dll")
    Loop

您需要声明此函数才能使用 GetModuleHandle(VBA7 版本):Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal GetModuleHandle As String) As LongPtr

另外,我用LongPtrVBA7 声明LoadLib 和FreeLib,如下所示:

Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
Private Declare PtrSafe Function FreeLibrary Lib "kernel32" (ByVal hLibModule As LongPtr) As Long

希望对你有帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-01
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多