"Ошибка времени выполнения" 453 "не удается найти точку входа dll" из скомпилированной dll vb.net, на которую ссылается vba - PullRequest
0 голосов
/ 12 мая 2010

Я кодирую в vb.net через visual studio 2008. Я успешно скомпилировал файл dll из своего кода, но продолжаю получать «Ошибка выполнения 453», когда пытаюсь ссылаться на dll в vba. Я понимаю, что при использовании vb.net возникает какая-то ошибка компиляции. Есть ли у кого-нибудь предложения, чтобы исправить / преодолеть эту проблему? Я хотел бы избежать перевода кода на другой язык в максимально возможной степени.

Вот простой пример кода, который я пытался заставить работать:

Example.dll:

Public Class Class1

    Function Square(ByVal x As Double, ByRef y As Double)

        y = x * x

        Return 0

    End Function

End Class

Макрос в Example.xlsx:

Private Declare Function Square Lib "\Example.dll" (ByRef x As Double, ByRef y As Double)

Sub Test()

Dim x, y As Double

x = 2
y = 0

Call Square(x, y)

MsgBox (y)

End Sub

Спасибо, Katlynn

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

Хорошо, куча вопросов здесь и предположения неверны.

Прежде всего, когда вы используете объявление в VBA для .dll, вы не можете использовать относительные имена путей.

Итак, у вас есть:

Private Declare Function Square Lib 
"\Example.dll" (ByRef x As Double, ByRef y As Double)

Вы не можете использовать \ Example.dll

Вы должны указать полное имя пути. Например:

C:\mytestApp\Example.dll

Таким образом, даже если vb.net действительно создал работающий .dll, вы должны использовать полное имя пути - относительный путь не допускается.

Вы можете поместить .dll в стандартные имена путей Windows, в которых выполняется поиск .dll (например, c: \ windows \ system32), и, таким образом, НЕ нужно использовать полный путь.

Однако, в наши дни с безопасностью, добавление или просто добавление .dll в системную папку Windows, как правило, имеет много проблем с безопасностью и ОГРОМНЫЕ проблемы. (Windows делает это сложно, как и любое вирусное программное обеспечение). Поэтому вы должны использовать полное имя пути.

Далее:

Использование объявления в VBA - это средство вызова API Windows, или то, что мы называем кодом библиотеки Windows x32 bit. Это не COM (ActiveX), но должен быть исходный код Windows x32 (или x64).

Так что это не объект ActiveX или «com», а необработанный код, который вы вызываете. Стандартный vb.net (или любой другой язык .net) НЕ производит собственный код Windows Правильный термин

Управляемый код = .net код. Этот код НЕ является родным кодом Windows.

Неуправляемый код = необработанный код Windows.

Таким образом, вы должны создать неуправляемый код для использования DECLARE в VBA.

Так что вы должны использовать: Ассемблер X86 C ++ VB6 Либо ЛЮБОЙ инструмент разработки, который может создавать raw x32 (или, если использовать access x64, то raw x64 собственный код Windows).

В настоящее время в Visual Studio вы «можете» создавать собственный код Windows, но вы должны использовать неуправляемый код, что означает c ++. (c # или vb.net не производят нативный код или библиотеки DLL).

Таким образом, вы можете использовать c ++, VB6 или даже ассемблер для создания этих .dll.

Такие .dll не требуют регистрации. И, как уже отмечалось, вы не создаете «экземпляр» объекта в коде VBA, а вызываете его напрямую.

Эти типы .dll (простые вызовы кода внешней библиотеки), таким образом, не отображаются как COM-объект. И если вы в VBA-редакторе идете инструменты-> ссылки, то вы не видите этих библиотек. Однако их можно легко использовать, поскольку вам не нужно создавать экземпляр VBA-кода объекта I - вы просто вызываете такой код, как в своем примере.

Поскольку имя пути жестко закодировано в этом подходе, часто бывает сложно использовать оператор DECLARE (поскольку он определяется во время компиляции VBA, а не во время выполнения). Это будет означать, что вы должны поместить этот .dll в то же место для каждого компьютера, на котором вы развертываете. Если вы переместите или измените папку, ваш код не будет работать.

Чтобы обойти эту проблему, вы можете использовать вызов LOADLIBARY в VBA. Это позволит вам во время выполнения установить (определить) местоположение .dll. Таким образом, большинство разработчиков, таким образом, просто помещают .dll в ту же папку в качестве запущенного приложения (ту же папку, что и Access, или, в данном случае, файл Excel).

Однако предполагается, что вы создаете стандартную библиотеку Windows .dll.

Могу ли я создавать такие собственные .dll Windows в .net с vb.net?

Оказывается, вы можете использовать некоторые внешние надстройки для VS. Я часто использую этот подход для создания этих dll, так как мне не нужно создавать код интерфейса COM, и он ОЧЕНЬ прост в использовании.

Затем я комбинирую вышеприведенное с VBA, используя вызов LOADLIBRARY, и это работает довольно хорошо. Таким образом, в VS вы можете использовать пакет NuGet (добавить) и выбрать утилиту для экспорта .dll. Их несколько, но я с большим успехом использовал DLL-импорт RGeseke. Это бесплатные сторонние решения здесь.

Пока вышеизложенное уменьшаютИз-за некоторых трудностей вам придется принять загрузочный библиотечный код VBA, чтобы сделать это практичным выбором (или всегда размещать .dll в одном месте). Я также рекомендую этот подход, если у вас есть некоторые существующие .dll, и вы хотите взаимодействовать с этим кодом, но не хотите изучать, скажем, c ++. Поэтому я использую этот подход, чтобы использовать существующие библиотеки DLL в vb.net и, следовательно, из Access. По сути, этот трюк позволяет вам писать интерфейсы для кода Windows .dll на хорошем знакомом языке, таком как vb.net.

Однако, если вы не использовали LOADlibrary из VBA (и VB6) в прошлом, и у вас не хватает скорости, то я предложу вам выбрать следующий вариант.

Создание COM (ActiveX) из vb.net

Это, вероятно, лучший подход. И это самый распространенный подход. Тем не менее, вы должны отказаться от необходимости создания COM-объекта в vb.net и затем зарегистрировать его на целевом компьютере.

Итак, единственное беспокойство - это требование зарегистрировать DLL на целевом компьютере.

Для регистрации (regasm.exe) COM-объекта на целевой машине часто требуются повышенные права. А поскольку в наши дни компании так заботятся о безопасности, это требование установки может стать проблемой, но, тем не менее, это, вероятно, лучший вариант.

Вот рабочий пример вашего кода в vb.net.

Imports System.Runtime.InteropServices

 <ClassInterface(ClassInterfaceType.AutoDual)>
Public Class Class1
    Function Square(ByVal x As Double) As Double

       Dim y As Double
       y = x * x

       Return y

   End Function

End Class

Обратите внимание на вышеизложенное, включая interop и настройку autoDuel в коде. Это то, что позволяет .net создавать стандартный интерфейс COM-объектов Windows, который может использоваться VBA, VB6, сценариями Windows или просто любой платформой, поддерживающей COM-объекты.

Настройки, необходимые для работы:

Принудительно .net проект для x86. (вы используете Excel x32).

Так что в VS зайдите в build-> менеджер конфигурации. Нажмите на платформу в сетке, выберите новую, выберите x86 и нажмите ОК.

Теперь вы должны иметь это: enter image description here

Далее убедитесь, что проект сделан видимым. Этот флажок ОБЯЗАТЕЛЬНО установлен для вас по умолчанию. Все классы .net имеют тенденцию быть отмеченными таким образом. Но я видел, что это не проверяется, когда вы возитесь с предыдущим шагом по изменению сборки на x86. Так что взгляните на этот параметр.

Проект-> Свойства

Теперь в области приложений нажмите на окно информации о сборке.

Вы должны убедиться, что установлен этот флажок:

enter image description here

Так что выше это займет всего несколько секунд.

Так проверьте выше (они обычно уже установлены для вас).

Далее мы должны указать VS зарегистрировать этот COM-объект на нашем компьютере разработчика. (это требование regasm.exe).

Итак, в области компиляции установите этот флажок:

enter image description here

Теперь, вышеупомянутый флажок в VS предназначен ТОЛЬКО для вашего компьютера разработки и удобства. Это просто делает для вас регазм, и это магия, которая выставляет класс как объект COM для использования в VBA или ЛЮБОЙ системе, которая поддерживает COM.

Обратите внимание, что вышеуказанный флажок предназначен ТОЛЬКО для вашего удобства на вашей машине для разработки. Он НЕ изменяет, не изменяет и не делает НИЧЕГО с кодом или проектом.

Теперь, чтобы развернуть этот код на других машинах, вам нужно предоставить командный файл или другие средства для выполнения команды regasm.exe. Как я уже отмечал, это значительно усложняет развертывание по сравнению с подходом .dll, но здесь вы компенсируете другую простоту кодирования.

На этом этапе скомпилируйте (соберите) вышеприведенное.

Как только вы это сделаете, вы теперь найдете в редакторе VBA, вы можете перейти в tools-> reference и найти ваш проект как зарегистрированный COM-объект для использования в VBA.

Вы видите это: (мой проект назывался Testcom2.

enter image description here

И обратите внимание, что как только вы установите эту ссылку, вы ДОЛЖНЫ ВЫЙТИ из Excel, если внесете изменения или перекомпилируете проект .net. (потому что EXCEL будет заблокирован и будет использовать этот .dll, как только вы установите эту ссылку). Так что просто помните, что если вы собираетесь пересобрать код .net, убедитесь, что вы выходите из Excel.

И я немного изменил ваш код, так как функция возвращает значение, а вы всегда возвращаете 0. Вы можете использовать вызов и использовать Sub, если хотите, но у вас есть функция, определенная в vb.net, и не определенная подпункт

Итак, в VBA у нас теперь есть это:

Sub TEst55()

  Dim cMySquare  As New TestCom2.Class1

  Dim a    As Double
  Dim b    As Double

  a = 10

  b = cMySquare.Square(a)

  Debug.Print b


End Sub

Обратите внимание, что даже intel-sense работает при вводе текста, поэтому эта функция отображается как метод в VBA.

enter image description here

И даже типы и пармы отображаются при вводе в VBA, например:

enter image description here

И нажав f5 в VBA для запуска кода, мы получим это как вывод:

100
0 голосов
/ 13 мая 2010

Прошло много времени с тех пор, как я это сделал, поэтому я не уверен, нужно ли это больше, но вы пытались добавить все атрибуты COM?

http://support.microsoft.com/Default.aspx?kbid=817248

...