如何在 VB6 中使 VB.NET DLL 可调用?
Posted
技术标签:
【中文标题】如何在 VB6 中使 VB.NET DLL 可调用?【英文标题】:How to make a VB.NET DLL callable in VB6? 【发布时间】:2021-12-27 18:56:00 【问题描述】:我用VB.NET在VS2017中做了一个DLL:
Imports System.Runtime.InteropServices
<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
Public Class ComClass1
#Region "COM GUIDs"
' These GUIDs provide the COM identity for this class
' and its COM interfaces. If you change them, existing
' clients will no longer be able to access the class.
Public Const ClassId As String = "c67bcd70-54d0-4498-97be-a5f954790dec"
Public Const InterfaceId As String = "7ef1a8ce-bcc1-464e-8dc3-fc164bdb7ea3"
Public Const EventsId As String = "9939eabd-1102-4e34-9735-54664e3536bd"
#End Region
' A creatable COM class must have a Public Sub New()
' with no parameters, otherwise, the class will not be
' registered in the COM registry and cannot be created
' via CreateObject.
Public Sub New()
MyBase.New()
End Sub
Public Xposition As Int32
Public GoX As Int32
Public Function MoveX() As Int32
Dim target As Int32
target = Convert.ToInt32(Rnd() * 1000)
Xposition = target
Return Xposition
End Function
Public Function ReadX() As Int32
Dim target As Int32
target = Convert.ToInt32(Rnd() * 1000 - GoX)
Xposition = target
Return Xposition
End Function
End Class
我在开发 Widows 10 PC 上以管理员身份编译了 DLL。 我将 DLL 文件复制到运行 VB6 的 Windows XP 目标机器并得到运行时错误 453。
VB6 代码:
Private Declare Function GSCloseServer Lib "GSWDLL32.DLL" () As Long
Private Declare Function MoveX Lib "C:\Temp\VB_Applications\My_DLL_Test\MyNewDLL.dll" () As Integer
Private Sub btnMove_Click()
Call test
End Sub
Private Sub btnStop_Click()
Dim Running As Integer
' Unload MyGraph
Set Form1 = Nothing
Running = GSCloseServer()
If Running = 0 Then
MsgBox "Close Server OK: " & Running, vbOKOnly
Else
MsgBox "Close Server Error " & Running, vbOKOnly
End If
Unload Me
End Sub
Private Sub test()
'txtbxReadBack.Text = ComClass1.Xposition
txtbxReadBack.Text = MoveX
End Sub
我以管理员身份运行 VS2017,因此 DLL 似乎已在开发 PC 上正确注册。
【问题讨论】:
你不需要那个构造函数。我知道文档说它是必需的,但是在 .Net 中,如果您没有为某个类型声明任何构造函数,它将为您生成无参数构造函数。 您在 VB.NET 中构建一个 COM 对象,因此您必须像 VB6 中的 COM 对象一样调用它,而不是像带导出的标准 dll 一样。 如何在VB6中将其称为com对象? 在vb6项目中,从Project-References中选择MyNewDLL接口。然后您可以定义和实例化 COM 对象,例如Dim oMyDLL = New namespace.ComClass1
和txtbxReadBack.Text = oMyDLL.MoveX
,删除函数声明。在测试机器上,您的程序集需要注册(regasm.exe)。可能是在开发机器上编译程序集执行了程序集的注册。
快速说明(现在与您的问题无关),您已将 MoveX 声明为 .Net 端的 Int32 和 VB6 端的 Integer。 VB6 整数是 2 个字节,但 .Net Int32 是 4 个字节。您应该使用 VB6 Long 代替,它也是 4 个字节。
tlb 是通过注册 dll 创建的,包含 COM 接口定义。在 vb6 Project-References 中引用 tlb。 dll 的注册还添加了指向 tlb 和 dll 的注册表项(以及它们的路径);不要在不重新注册的情况下移动 dll。构建 dll 时,(在 VS2019 中)My Project-Compile 下有一个“Register for COM interop”复选框;选中该选项后,VS 在构建期间将注册 dll。但如果你没有引用那台电脑上的 dll(例如来自 vb6),你实际上不需要在那里注册它。
【参考方案1】:
这些是步骤。我将用一个类创建一个非常简单的“COMVisibleHelloWorld”类库
Imports System.Runtime.InteropServices
'Create a manual interface so we can use a fixed and known guid for the COM interface.
<Guid("3BBA8F8E-6B35-48E0-91D4-124DC6FCE7B9"), InterfaceType(ComInterfaceType.InterfaceIsDual)>
Public Interface IHelloWorld
<DispId(1)> Function SayHello() As String
End Interface
<Guid("BCDCDA5C-DCAF-4C6C-86BA-03908DBEFF4B"), ClassInterface(ClassInterfaceType.None)>
Public Class HelloWorld
Implements IHelloWorld
Public Function SayHello() As String Implements IHelloWorld.SayHello
Return "Hello World"
End Function
End Class
在 Visual Studio 中选择“使程序集 COM 可见”
在 Visual Studio 中创建强键
构建项目。这将创建一个 tlb 文件。
您现在可以参考这是 VB6
要在 VB6 中使用,只需创建一个实例,然后调用具有 COM 接口的方法
Private Sub Command1_Click()
Dim hello As New COMVisibleHelloWorld.HelloWorld
MsgBox (hello.SayHello)
End Sub
结果:
【讨论】:
我按照 COMVisibleHelloWorld 的说明进行操作,但在编译时没有创建 tlb 文件:只有 .dll、.pdb。 AMD .xml。 好的,我在编译选项菜单上找到了“Register for COM interop”复选框并选中它。现在我有了 tlb 文件! 32位XP、VB6目标机产生运行时错误429,ActiveX组件无法创建对象。我引用了 tlb 文件。公共函数“SayHello”出现在自动完成中。我在 64 位和 x86 位配置中构建了 dll。都没有奏效。该dll位于源代码目录中。我也在 System32 中尝试过。 Private Declare Function SayHello Lib "C:\Temp\VB_Applications\My_DLL_Test\COMVisibleHelloWorld.tlb" () As String Private Sub btnMove_Click() Dim hello As New COMVisibleHelloWorld.HelloWorld Dim test As String MsgBox (hello.SayHello) End Sub 我尝试注册dll,提示无法注册文件。我想这可以吗? 要检查 dll 是否已注册,打开命令提示符并运行:“reg query HKLM\SOFTWARE\Classes /s /f COMVisibleHelloWorld.dll”这将搜索注册表并尝试查找 dll以上是关于如何在 VB6 中使 VB.NET DLL 可调用?的主要内容,如果未能解决你的问题,请参考以下文章
VB.net调用DLL,捕捉到AccessVioationException尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
vb6中的RtlMoveMemory ByVal a,在vb.net中应如何表达?