Ошибка VBA 49 и ошибка 424 при вызове C# DLL из Access VBA с использованием unmamagedexports

В нашей среде наше основное приложение использует 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, но результат всегда был одинаковым. Я был очень удивлен, что мне не удалось заставить этот пример работать, так как я ввел его прямо из другого поста, и я дважды проверил, чтобы убедиться, что он был скопирован правильно. Любая помощь будет принята с благодарностью.

Все это кажется неправильным, отсюда я могу обнаружить как минимум 3 ошибки. Не могу заставить UnmanagedExports работать на моем компьютере, поэтому я не могу должным образом написать ответ, так как их можно найти еще больше, но я настоятельно рекомендую вам просто зарегистрировать библиотеки DLL. Если проблема связана с правами администратора или установщика, вы можете зарегистрировать их в HKCU вместо HKLM (не требует доступа администратора) и зарегистрировать их для определенного пути (не требует доступа к C: \ Windows, может быть на сетевой диск)

Erik A 12.12.2018 10:09

Это стандартные ошибки DLL Hell, поэтому неуправляемый экспорт всегда становится ужасно быстрым. Функция, которую вы объявили в VBA, не соответствует реальному методу, который ее реализует. Мы не можем увидеть фактический метод, но наличие дополнительного параметра было бы наиболее типичной причиной. Противоборствующие отношения с ИТ-персоналом заказчика никогда не являются проблемой, которую следует решать с помощью программного обеспечения.

Hans Passant 12.12.2018 12:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
273
1

Ответы 1

Ваша декларация для 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 обнаруженных мной ошибок. Все равно не сработает. По крайней мере, оставшиеся ошибки: не могут возвращать ссылочные типы из неуправляемых функций (вместо этого следует использовать выходной параметр), объект, вероятно, не будет немаршалирован после его такого маршалинга. Но как сказал, возможно еще больше ошибок.

Erik A 12.12.2018 11:55

Другие вопросы по теме