代码之家  ›  专栏  ›  技术社区  ›  MartW

VB6在使用活动Windows消息挂钩进行调试时退出

  •  2
  • MartW  · 技术社区  · 17 年前

    我们最大的一个旧的vb6应用程序中有一些代码,允许其他应用程序(包括一些dotnet应用程序)通过Windows消息向其传递ID-然后vb6应用程序使用此ID加载常规Windows窗体中的条目。消息钩子是在用户登录和验证之后添加的,并在用户注销后删除。

    Public Sub HookClaimFinderCall()
        lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
    End Sub
    
    Public Sub UnhookClaimFinderCall()
        Dim temp As Long
        If gHW <> 0 Then temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
    End Sub
    
    Private Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        If uMsg = WM_FINDCLAIM Then
            MasterFindClaim lParam
        End If
        WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
    End Function
    

    但是,这有两个问题。第一个与Visual Studio 6有关。如果正在调试代码,并且在弹出“继续结束调试帮助”对话框时出错,则按“结束”立即退出Visual Studio(丢失所有未保存的更改)。如果消息挂钩尚未激活,则不会发生这种情况。是什么导致了这种情况,除了注释掉加载钩子的代码,我还能做些什么来阻止它呢?

    其次,如果用户不正确地退出应用程序(无论以何种方式),那么消息挂钩会发生什么情况?

    我希望我已经掌握了上面所有的条件…

    2 回复  |  直到 17 年前
        1
  •  5
  •   Kris Erickson    17 年前
    1. 如果您启动一个全局钩子并尝试在VB6中进行调试,您将遇到崩溃(或VB6消失)。vb6有点像一个模拟器,它不完全复制vb6应用程序的运行时,挂接是它严重失败的一个方面(尽管如果你理解了发生的事情,就不必责怪它)。对于我们在应用程序中使用的所有全局钩子,我们将检查vb6是否在IDE模式下运行(有几种方法可以这样做),如果是,则不要运行全局钩子。如果必须运行全局挂接,请不要在调试器中停止应用程序-使用debug.print或其他方法,但不要停止应用程序,否则在应用程序“消失”之前,您将有几毫秒到几秒的时间。
    2. 虽然您应该在退出应用程序之前取消挂起,但是当消息泵碰到钩子并且钩子发生的应用程序的句柄不再存在时,忽略钩子是一个相当简单的操作。现在,如果您运行应用程序并退出数千次,它可能会累积起来,但我认为这是您最不关心的问题。
        2
  •  3
  •   MarkJ    17 年前

    克里斯的回答是正确的。另外几点。

    • 严格地说,这是子类化,而不是消息挂钩。
    • 这也是你的好习惯 WindProc 当收到消息时检测wm_ncDestroy并取消挂起。这条消息意味着窗口即将被破坏——无论用户如何退出应用程序,都应该收到它。
    • 在Windows2000和更高版本中,有一些API调用使得管理子类化更加容易。像往常一样,卡尔·彼得森有一篇优秀的文章,文章中有优秀的VB6代码 here .