在我们的环境中,我们的主应用程序使用MS Access作为前端。后端是Access,MySQL和MariaDB。我们需要的某些例程仅在C#中可用,因此我们必须能够从VBA调用.NET dll例程。我使用注册的dll(使用RegASM)进行了一些测试,并且工作正常。但是,对于在客户端计算机上的安装,我们确实需要能够在不注册共享dll的情况下访问它们。
我一直试图让MS Access VBA中的动态加载库工作很长时间了。发现以下示例时,我以为自己很亲近:Canonical: How to call .NET methods from Excel VBA
我逐字键入示例,并使用Visual Studio 2017社区对其进行了构建。然后,我尝试在两个不同的测试环境中运行它。首先是带有MS Office Pro 2010(32位)的Windows 7 Pro(64位)盒。第二个测试框具有Windows 10 Pro(64位)和MS Office 2016 Pro(64位)。除错误编号/消息外,两者的结果相同。
这是上面链接的示例代码(我希望重新发布该片段不会违反礼节。我想使此帖子更容易理解):
[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class YOUR_MAIN_CLASS
{
[return: MarshalAs(UnmanagedType.BStr)]
public string FN_RETURN_TEXT(string iMsg)
{
return "You have sent me: " + iMsg + "...";
}
}
static class UnmanagedExports
{
[DllExport]
[return: MarshalAs(UnmanagedType.IDispatch)]
static Object YOUR_DLL_OBJECT()
{
return new YOUR_MAIN_CLASS();
}
}
这是VBA代码。唯一的区别是,我没有在Access 2010 32位测试中使用“ PtrSafe”限定词,但在Access 2016 64位Access测试中使用了它。我将Visual Studio Platform Target设置为使用32位Access进行测试的x86和设置为64位Access的x64。除此之外,一切都一样。
Option Compare Database
Option Explicit
Public Declare PtrSafe Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
Public Declare PtrSafe Function YOUR_DLL_OBJECT Lib "NonRegisteredDLL.dll" ()
Public Sub TestLoad()
LoadLibrary ("C:\Users\lab\Documents\Visual Studio 2017\Projects\NonRegisteredDLL\NonRegisteredDLL\bin\Debug\NonRegisteredDLL.dll")
Dim mObj As Object
' Error occurs on next line
Set mObj = YOUR_DLL_OBJECT()
Debug.Print mObj.FN_RETURN_TEXT("Testing...")
End Sub
运行代码时,错误始终发生在“ Set mObj”行。
在Access 2010 32位测试中,错误为:
运行时错误“ 49”: 错误的DLL调用约定
在Access 2016 64位测试中,错误是:
运行时错误“ 424”: 所需对象
在两个测试中,我都运行了DumpBin,结果似乎还不错:
>dumpbin nonregistereddll.dll /exports
Dump of file nonregistereddll.dll
File Type: DLL
Section contains the following exports for \NonRegisteredDLL.dll
00000000 characteristics
5C0FF158 time date stamp Tue Dec 11 10:18:16 2018
0.00 version
0 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
0 0 0000283E YOUR_DLL_OBJECT
Summary
2000 .reloc
2000 .rsrc
2000 .sdata
2000 .text
>
基于此处关于stackoverflow的其他几篇文章,我还对DllExport上的CallingConvention参数进行了实验,但结果始终相同。我无法从另一个帖子中直接输入该示例,我感到非常惊讶,我再次检查以确保正确复制了该示例。任何帮助将不胜感激。
答案 0 :(得分:0)
您对DLL的声明不完整或缺少Data Type
。更改
Public Declare PtrSafe Function YOUR_DLL_OBJECT Lib "NonRegisteredDLL.dll" ()
到
Public Declare PtrSafe Function YOUR_DLL_OBJECT Lib "NonRegisteredDLL.dll" () As Object
注意
Visual Basic的早期版本允许您将参数声明为 任何,表示可以使用任何数据类型的数据。 Visual Basic 要求您为所有Declare语句使用特定的数据类型。
read more here 然后重试。