COM App调用.NET表单调用COM表单,在编译时工作但在VB6 IDE中不工作

时间:2013-12-11 00:11:30

标签: vb.net winforms com vb6 com-interop

我有一个遗留的VB6 / COM应用程序,我们正在通过.NET DLL将所有代码迁移到.NET(VB.NET)。所有新的表单开发都在.NET DLL中完成。

我们使用函数指针回调.NET表单中的COM函数:

  1. 我在.NET中创建一个委托
  2. 在运行时将委托设置为AddressOf COM函数(GetDelegateForFunctionPointer)
  3. 显示.NET表单
  4. 调用代理
  5. COM App - > .NET表单 - > COM功能

    这适用于各种功能。这种情况发生在我调用显示表单的COM函数时。

    COM App - > .NET表单 - > COM功能 - > COM表格

    将执行COM函数并显示表单,但在VB6 IDE中执行时,COM表单的逻辑不会执行。显示控件,但不执行任何click或form_load事件。编译VB6应用程序时,这不是问题。

    我注意到的另一个问题是VB6 IDE“冻结”,直到.NET表单卸载。我无法停止调试器,设置断点或与IDE的菜单交互。就好像VB6 IDE允许.NET DLL完全控制线程一样。我相信这两个问题是相关的。

    编辑: .NET表单是模态的,这可能是IDE线程锁定的原因。我只是想知道是否有办法绕过它。另外,我查看了InteropForms Toolkit。它没有解决我的问题。即使将其样本表单设置为模态也会导致发生相同的IDE线程锁定。

    编辑2: 我之前的编辑确实暗示了另一种解决方法:当主机应用程序是VB6时,使.NET表单显示为无模式。

    If InStr(Process.GetCurrentProcess().ProcessName, "vb6", CompareMethod.Text) > 0 Then
        frm.Show()
    Else
        frm.ShowDialog()
        frm.Dispose()
    End If
    

2 个答案:

答案 0 :(得分:3)

简单的COM应用程序 - > .NET表单 - > COM功能 - > COM表单方案可以使用InteropForms Toolkit 2.1。以下是一些代码,无需使用委托或AddressOf

首先,我们有我们的COM库,我将其称为ComLibrary。我们有以下代码:

<强> SimpleForm.frm:

Option Explicit

Private Sub Form_Load()
    MsgBox "In SimpleForm_Load"
End Sub

Private Sub OkButton_Click()
    Unload Me
End Sub

Private Sub TalkButton_Click()
    MsgBox "Hello"
End Sub

<强> SimpleClass.cls:

Option Explicit

Public Function ShowTheDialog() As Long
    Dim f As SimpleForm

    Set f = New SimpleForm

    f.Show vbModal

    ShowTheDialog = 1

End Function

将其编译为.dll,以便我们可以在.NET库中引用它。

接下来,我们将创建.NET表单库。我使用&#34; VB6 InteropForms Library&#34;项目模板使用默认项目名称InteropFormsLibrary1。我添加了对ComLibrary项目的引用。表单有一个名为&#34; CallComFunction。&#34;

的按钮

<强> InteropForm1.vb:

Imports Microsoft.InteropFormTools

<InteropForm()> _
Public Class InteropForm1
    Private Sub CallComFunction_Click(sender As System.Object, e As System.EventArgs) Handles CallComFunction.Click
        Dim sc As ComLibrary.SimpleClass
        sc = New ComLibrary.SimpleClass

        Dim result As Integer
        result = sc.ShowTheDialog()
    End Sub
End Class

在编译之前,我们需要根据工具包文档创建InteropForms包装类。通过访问工具&gt;来执行此操作Generator InteropForms Wrapper Classes菜单。

最后,我们创建了VB6主机应用程序。

<强> Form1.frm:

Option Explicit

Private Sub DialogButton_Click()
    Dim f As InteropFormLibrary1.InteropForm1

    Set f = New InteropForm1

    f.Show vbModal

End Sub

当我在VB6 IDE中运行主机应用程序时,我可以单击VB6表单按钮,然后显示VB.NET表单。从那里,我单击另一个按钮,它使用SimpleClass的实例来显示SimpleForm。表单加载事件和按钮单击处理程序中的MsgBox语句有效。在编译VB6主机应用程序时一切正常。

答案 1 :(得分:2)

看起来你的VB6 IDE正在将你的VB应用程序作为“进程内”COM对象加载,虽然这对我来说没有多大意义......但是如果是这样的话,那就意味着你有一个您的应用程序和调试器的单个消息循环,这可能至少解释其中一些问题。我多年没有使用过VB-classic IDE,所以我不知道它是如何工作的。也许在某个地方有一个选项可以在一个单独的进程中加载​​你的应用程序?

更新 - 看来我猜是正确的。有关更多信息和可能的解决方法,请参阅此其他问题及其答案:

https://stackoverflow.com/a/518217/501196