В нашей среде наше основное приложение использует MS Access для внешнего интерфейса.Бэкэндами являются Access, MySQL и MariaDB.Некоторые из необходимых нам подпрограмм доступны только в C #, поэтому мы должны иметь возможность вызывать подпрограммы .NET dll из VBA.Я провел некоторое тестирование с зарегистрированными dll (используя RegASM), и оно работало нормально.Однако для установки на клиентских компьютерах нам действительно нужно иметь возможность получить доступ к общим dll без их регистрации.
Я пытался заставить динамически загруженные библиотеки в MS Access VBA работать долгое время.сейчас.Мне показалось, что я был близок, когда нашел этот пример: Canonical: как вызывать методы .NET из Excel VBA
Я набрал дословно пример и построил его с помощью сообщества Visual Studio 2017.Затем я попытался запустить его в двух разных тестовых средах.Первым был Windows 7 Pro (64-битный) с MS Office Pro 2010 (32-битный).Второй тестовый блок имеет 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.Единственное отличие состоит в том, что я не использовал квалификатор PtrSafe в 32-разрядном тесте Access 2010, но использовал его для 64-разрядного теста Access 2016.Я установил для Visual Studio Platform Target значение x86 для теста с 32-битным доступом и x64 для 64-битного доступа.Кроме этого все было одинаково.
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».
В 32-разрядном тесте Access 2010 ошибка:
Ошибка времени выполнения '49': неверное соглашение о вызове DLL
В 64-разрядном тесте Access 2016ошибка:
Ошибка времени выполнения '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, я также экспериментировал с параметром CallingConvention на DllExport, но результат всегда был одинаковым.Я был очень удивлен, что не смог заставить пример работать, поскольку я ввел его непосредственно из другого поста, и я дважды проверил, чтобы убедиться, что он был скопирован правильно.Любая помощь будет принята с благодарностью.