使用 VB6 IDE END 调试时未调用 Dispose 和/或 Finalize

发布于 2024-11-11 06:54:46 字数 862 浏览 1 评论 0原文

继我不久前的问题之后。

我已经解决了与此相关的大部分部分。 检测 COM 对象何时超出范围

I现在,开发人员在处理 VB6 代码时面临一个新问题。如果他们在 IDE 中运行项目,然后按 END,则将调用 Dispose 或 Finalize。这就像 VB6 的调试部分只是立即分离,而不调用 disposes 等。

我已经通过使用标准应用程序关闭和从 COM 调用 Finalize 进行了测试 -> .NET 组件和我的线程关闭,但如果按下“结束”按钮,则不会执行 Finalise,不会执行 Dispose,并且我的线程会继续运行。

在我的组件中我尝试了这个

bool debuggerAttachedatStart = System.Diagnostics.Debugger.IsAttached;
System.Windows.Forms.MessageBox.Show("The Debugger is currently -" + debuggerAttachedatStart);

,但是当你在 VB6 中运行它时,它总是 False。

我拿出 Process Explorer 并查看了 VB6,我注意到它在启动调试会话时创建了一个 Event 对象,但每次启动时它都是一个唯一的 guid。 (\Sessions\1\BaseNamedObjects{70FAF0B5-A76B-4C6A-92BE-5201B2335871})

只是想知道我是否可以做些什么,以便我可以优雅地检测到调试已在 VB6 中停止(或开始)。

Following on from my question a little while ago.

I have resolved most of the parts related to that.
Detect when a COM Object goes out of Scope

I now face a new problem whilst developers are working on the VB6 code. If they run the project inside the IDE, and then press END, the Dispose nor Finalize are being called. It's like the Debugging part of VB6 just detaches immediately without calling disposes etc.

I have tested this via using the standard application close and Finalize gets called from COM -> .NET component and my thread shuts down, but if the End button is pressed there is no Finalise, no Dispose and my thread just keeps running.

Inside my component I tried this

bool debuggerAttachedatStart = System.Diagnostics.Debugger.IsAttached;
System.Windows.Forms.MessageBox.Show("The Debugger is currently -" + debuggerAttachedatStart);

but when you run it within VB6, it's always False.

I got out Process Explorer and had a look at VB6 and I noticed it creates an Event object upon startup of the Debugging session, but it is a unique guid each time you start. (\Sessions\1\BaseNamedObjects{70FAF0B5-A76B-4C6A-92BE-5201B2335871})

Just wondering if there is anything I can do so that I can gracefully detect that the Debugging has stopped (or started) within VB6.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

朦胧时间 2024-11-18 06:54:46

不,你无能为力。停止调试并不会让您的程序有机会运行代码。

No, there is nothing you can do. Stopping debugging does not give your program a chance to run code.

错爱 2024-11-18 06:54:46

我相信我可能已经找到了一个解决方案,并认为我会分享它,以防有人对如何优雅地关闭线程有更好的想法。

在我的 .NET 程序集中添加另一个事件定义

<InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Manager.EventsId)> _
Public Interface IManagerEvents
    'Others Removed
    <DispId(4)> Sub HostAlive(ByRef alive As Boolean)
End Interface

,然后在代码定义中添加
Public Delegate Sub HostAliveDelegate(ByRef state As Boolean)

现在在代码的主要区域中,因为我们将与 VB6 对话,所以我们需要位于正确的线程上,因此获取 SyncContext。并设置线程。

public sub New()
    Dim operation As ComponentModel.AsyncOperation
    operation = AsyncOperationManager.CreateOperation(Nothing)
    mSync = AsyncOperationManager.SynchronizationContext
    operation.OperationCompleted()
    'setup thread work.....
end sub 

Private Sub ConnectPipe()
    Dim lastAliveCheck As DateTime
    lastAliveCheck = DateTime.Now.AddSeconds(2)
    While Not mRunningEvent.Wait(0)


      'do all the work to prepar and setup the PIPE.
      'if we successfully connect
        Using NoOpTimer As New Threading.Timer(New Threading.TimerCallback(AddressOf TimerTicks), mPipe, 2000, 2000)
            'If we disconnect, this Event gets allowing the exit and reconnect to commence
            mConnectedHold.WaitOne()
        End Using

        'we must have not connected so ensure that we are still inside a running process
            PipeLog.Write("Attempting reconnect to named pipe")
            mConnectedStopper.Wait(500)
            If DateTime.Now > lastAliveCheck Then
                lastAliveCheck = DateTime.Now.AddSeconds(2)
                Dim e As New HostAliveEventArgs()
                OnHostAlive(e)
                If Not e.IsAlive Then
                    'The host did not set the event. Make sure the event is wired up and setting the value to true.
                    Exit While
                End If
            End If
    End While
    DisposePipe
    mExitingEvent.Set()
End Sub       

Protected Sub OnHostAlive(ByVal e As HostAliveEventArgs)
    mSync.Send(AddressOf OnHostAliveContextPost, e)
End Sub

Private Sub OnHostAliveContextPost(ByVal state As Object)
    Dim e As HostAliveEventArgs = CType(state, HostAliveEventArgs)
    RaiseEvent HostAlive(e.IsAlive)
End Sub   

我们的 VB6 类内部使用了该组件。

Private WithEvents comm As IPSClient_Intercommunication.Manager

Private Sub Class_Initialize()
    Set comm = New IPSClient_Intercommunication.Manager
End Sub

Private Sub comm_HostAlive(ByRef alive As Boolean)
    alive = True
End Sub

我发现,即使您使用 CustomEvent,它也始终是绑定的,因此您不能仅仅确定没有连接的事件委托并断开连接。当您在主机应用程序已关闭的情况下引发该事件时,该事件不会将活动设置为 true,并且您可以假设它已被中止。

I believe I may have found a solution and thought I'd share it, incase someone has a better idea for how I can gracefully perform the shutdown of my thread.

In my .NET assembly add another Event definition

<InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Manager.EventsId)> _
Public Interface IManagerEvents
    'Others Removed
    <DispId(4)> Sub HostAlive(ByRef alive As Boolean)
End Interface

and in the Code Definition add
Public Delegate Sub HostAliveDelegate(ByRef state As Boolean)

Now in the main area of Code, because we will be talking to VB6 we need to be on the correct thread, so grab a SyncContext. And setup the threads.

public sub New()
    Dim operation As ComponentModel.AsyncOperation
    operation = AsyncOperationManager.CreateOperation(Nothing)
    mSync = AsyncOperationManager.SynchronizationContext
    operation.OperationCompleted()
    'setup thread work.....
end sub 

Private Sub ConnectPipe()
    Dim lastAliveCheck As DateTime
    lastAliveCheck = DateTime.Now.AddSeconds(2)
    While Not mRunningEvent.Wait(0)


      'do all the work to prepar and setup the PIPE.
      'if we successfully connect
        Using NoOpTimer As New Threading.Timer(New Threading.TimerCallback(AddressOf TimerTicks), mPipe, 2000, 2000)
            'If we disconnect, this Event gets allowing the exit and reconnect to commence
            mConnectedHold.WaitOne()
        End Using

        'we must have not connected so ensure that we are still inside a running process
            PipeLog.Write("Attempting reconnect to named pipe")
            mConnectedStopper.Wait(500)
            If DateTime.Now > lastAliveCheck Then
                lastAliveCheck = DateTime.Now.AddSeconds(2)
                Dim e As New HostAliveEventArgs()
                OnHostAlive(e)
                If Not e.IsAlive Then
                    'The host did not set the event. Make sure the event is wired up and setting the value to true.
                    Exit While
                End If
            End If
    End While
    DisposePipe
    mExitingEvent.Set()
End Sub       

Protected Sub OnHostAlive(ByVal e As HostAliveEventArgs)
    mSync.Send(AddressOf OnHostAliveContextPost, e)
End Sub

Private Sub OnHostAliveContextPost(ByVal state As Object)
    Dim e As HostAliveEventArgs = CType(state, HostAliveEventArgs)
    RaiseEvent HostAlive(e.IsAlive)
End Sub   

Over inside our VB6 class that utilises this component.

Private WithEvents comm As IPSClient_Intercommunication.Manager

Private Sub Class_Initialize()
    Set comm = New IPSClient_Intercommunication.Manager
End Sub

Private Sub comm_HostAlive(ByRef alive As Boolean)
    alive = True
End Sub

What I discovered is that even if you use a CustomEvent it is always bound, so you can't just determine that there are no connected event delegates and disconnect. When you raise the event if the host application has been shutdown, then the event doesn't set the alive to true, and you can assume that it's been aborted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文