title: VBA error 49 and error 424 when calling C# DLL from Access VBA using unmamagedexports
body: <p>In our environment our main application uses MS Access for a front-end. The back-ends are Access, MySQL and MariaDB. Some of the routines we need are only available in C# so we have to be able to call .NET dll routines from VBA. I did some testing with registered dlls (using RegASM) and it worked fine. However, for the installs on client machines, we really need to be able to get to the shared dlls WITHOUT registering them.</p>
  
  <p>I have been trying to get dynamically loaded libraries in MS Access VBA to work for a long time now. I thought I was close when I found this example: <a href="https://stackoverflow.com/questions/37074533/canonical-how-to-call-net-methods-from-excel-vba">Canonical: How to call .NET methods from Excel VBA</a></p>
  
  <p>I typed in the example verbatim and built it using Visual Studio 2017 Community. Then I tried to run it in two different test environments. The first was a Windows 7 Pro (64 bit) box with MS Office Pro 2010 (32 bit). The second test box has Windows 10 Pro (64 bit) and MS Office 2016 Pro (64 bit). The result was the same on both, except for the error number/message. </p>
  
  <p>Here is the sample code from the above link (I hope reposting the snippet is not a breach of etiquette. I wanted to make this post easier to follow):</p>
  
  <pre><code>[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();
      }
  }
  </code></pre>
  
  <p>Here is the VBA code. The only difference is that I did not use the "PtrSafe" qualifier in the Access 2010 32 bit test, but I did use it for the Access 2016 64 bit Access test. I set the Visual Studio Platform Target to x86 for the test with 32 bit Access and to x64 for the 64 bit Access. Other than that, everything was the same. </p>
  
  <pre><code>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
  </code></pre>
  
  <p>When the code is run, the errors always occur at the "Set mObj" line. </p>
  
  <p>In the Access 2010 32 bit test, the error is:</p>
  
  <p>Run-time error '49':
  Bad DLL calling convention</p>
  
  <p>In the Access 2016 64 bit test, the error is:</p>
  
  <p>Run-time error '424':
  Object required</p>
  
  <p>On both tests, I ran DumpBin and the result seemed fine:</p>
  
  <pre><code>&gt;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
  
  &gt;
  </code></pre>
  
  <p>Based upon a few other posts here on stackoverflow, I also experimented with the CallingConvention parameter on the DllExport but the result was always the same. I was very surprised that I couldn't get the example to work as I had entered it directly from the other post and I double-checked to make sure it was copied correctly. Any help would be greatly appreciated.</p>