В нашей среде наше основное приложение использует MS Access для интерфейса. Бэкэнды - это Access, MySQL и MariaDB. Некоторые из необходимых нам подпрограмм доступны только в C#, поэтому мы должны иметь возможность вызывать подпрограммы .NET dll из VBA. Я провел некоторое тестирование с зарегистрированными dll (используя RegASM), и он работал нормально. Однако для установки на клиентские машины нам действительно нужно иметь возможность получить доступ к общим dll БЕЗ их регистрации.
Я давно пытаюсь заставить работать динамически загружаемые библиотеки в MS Access VBA. Я подумал, что близок, когда нашел этот пример: Канонический: как вызвать методы .NET из Excel VBA
Я ввел пример дословно и построил его с помощью Visual Studio 2017 Community. Затем я попытался запустить его в двух разных тестовых средах. Первым был 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 на 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
При запуске кода ошибки всегда появляются в строке «Установить 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, но результат всегда был одинаковым. Я был очень удивлен, что мне не удалось заставить этот пример работать, так как я ввел его прямо из другого поста, и я дважды проверил, чтобы убедиться, что он был скопирован правильно. Любая помощь будет принята с благодарностью.
Это стандартные ошибки DLL Hell, поэтому неуправляемый экспорт всегда становится ужасно быстрым. Функция, которую вы объявили в VBA, не соответствует реальному методу, который ее реализует. Мы не можем увидеть фактический метод, но наличие дополнительного параметра было бы наиболее типичной причиной. Противоборствующие отношения с ИТ-персоналом заказчика никогда не являются проблемой, которую следует решать с помощью программного обеспечения.





Ваша декларация для 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
Note
Previous versions of Visual Basic allowed you to declare parameters As Any, meaning that data of any data type could be used. Visual Basic requires that you use a specific data type for all Declare statements.
подробнее здесь и попробуй еще раз.
Это 1 из 3 обнаруженных мной ошибок. Все равно не сработает. По крайней мере, оставшиеся ошибки: не могут возвращать ссылочные типы из неуправляемых функций (вместо этого следует использовать выходной параметр), объект, вероятно, не будет немаршалирован после его такого маршалинга. Но как сказал, возможно еще больше ошибок.
Все это кажется неправильным, отсюда я могу обнаружить как минимум 3 ошибки. Не могу заставить UnmanagedExports работать на моем компьютере, поэтому я не могу должным образом написать ответ, так как их можно найти еще больше, но я настоятельно рекомендую вам просто зарегистрировать библиотеки DLL. Если проблема связана с правами администратора или установщика, вы можете зарегистрировать их в HKCU вместо HKLM (не требует доступа администратора) и зарегистрировать их для определенного пути (не требует доступа к C: \ Windows, может быть на сетевой диск)