使用unmamagedexports从Access VBA调用C#DLL时,VBA错误49和错误424

时间:2018-12-11 22:12:07

标签: c# vba access-vba loadlibrary unmanagedexports

在我们的环境中,我们的主应用程序使用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参数进行了实验,但结果始终相同。我无法从另一个帖子中直接输入该示例,我感到非常惊讶,我再次检查以确保正确复制了该示例。任何帮助将不胜感激。

1 个答案:

答案 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 然后重试。