2016-11-18 5 views
2

У меня есть 64-разрядное приложение VB.Net, которому необходимо использовать 32-разрядную неуправляемую DLL сторонней организации.Невозможно вызвать 32-разрядную неуправляемую DLL из 64-разрядного управляемого кода

Вот вещи, которые я пробовал:

  1. Я создал 32-битную библиотеку vb.net класса обертки, которая называется COM1, и добавил VB.Net COM класс, который вызывает 32-разрядный неуправляемые функции dll. В проекте включен «Регистрация для COM-взаимодействия». Когда я сослалась на 32-битную DLL (COM1.dll) к моему 64-разрядного приложения и выполняется приложение, я получил следующее исключение:

    Не удалось загрузить файл или сборку «COM1.dll» .. . Была сделана попытка загрузить программу с неправильным форматом.

  2. Я создал 64-битную библиотеку классов vb.net обертка, которая называется COM2, и добавил VB.Net COM класс, который называет 32-битную DLL неуправляемый. В проекте включен «Регистрация для COM-взаимодействия». Когда я ссылался на 64-разрядную DLL (COM2.dll) в своем 64-битном приложении и выполнял приложение, мне удалось загрузить 64-разрядную dll, но я получил следующее исключение, когда я назвал одну из функций, неуправляемая dll (через 64-разрядную обертку dll):

    Попытка загрузить программу с неправильным форматом.

  3. Я попытался выполнить описанные выше шаги с помощью приложения WCF, где я заменяю COM-оболочку службой WCF, но получаю тот же результат.

Я понимаю, что я не могу назвать 32-разрядную dll непосредственно из своего 64-битного приложения. То, что я пытаюсь сделать, это вызвать 32-разрядную DLL через механизм IPC — в этом случае COM или WCF. Очевидно, я ошибаюсь здесь.

Может ли кто-нибудь дать мне рабочий код или сообщить мне, что я делаю неправильно на вышеупомянутых шагах?


Часть моего кода:

  1. Мой COM класс

    <ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _ 
    Public Class ComClass1 
        Public Declare Sub InitializePort Lib "I2CDrvrs" (ByVal I2cAddr As Byte, ByVal evalBoardUsed As Byte) 
    
    #Region "COM GUIDs" 
        ' These GUIDs provide the COM identity for this class 
        ' and its COM interfaces. If you change them, existing 
        ' clients will no longer be able to access the class. 
        Public Const ClassId As String = "5da6d3a4-848c-42b1-bc7c-4079ec5457b1" 
        Public Const InterfaceId As String = "8de9508b-fda6-496e-bb29-a90dc5282d2c" 
        Public Const EventsId As String = "cfec40ff-fec0-4250-9d72-9d63f1e37d21" 
    #End Region 
    
        ' A creatable COM class must have a Public Sub New() 
        ' with no parameters, otherwise, the class will not be 
        ' registered in the COM registry and cannot be created 
        ' via CreateObject. 
        Public Sub New() 
         MyBase.New() 
        End Sub 
    End Class 
    
  2. Мой 64-разрядное приложение

    Public Function foo() As Boolean 
        Try 
         COM1.ComClass1.InitializePort(2, 2) 
        Catch ex As Exception 
         MsgBox(ex.ToString) 
        End Try 
        Return True 
    End Function 
    

ответ

0

Я нашел довольно простое решение моей проблемы. Я реализовал модель клиент-сервер с использованием методов и свойств класса Socket. Я запускаю 32-разрядный код управляемого управления, работающий как сервер. Сервер вызывает функции 32-разрядной неуправляемой dll. Таким образом, сервер работает как обертка для неуправляемой dll. Я использую свое 64-битное приложение как клиент. Я передаю строку на сервер от моего клиента. Строка содержит информацию о вызываемой функции и ее аргументах. Я разбираю строку на сервере и вызываю соответствующую функцию в неуправляемой dll.

0

Приведение в COM-DLL в качестве промежуточного (будь то 32-разрядного или 64-битного) не решает проблему. Вы по-прежнему пытаетесь загрузить эту 32-битную библиотеку в свой 64-битный процесс. Никакое количество трюков COM не исправит это.

32-разрядная библиотека должна запускаться изнутри 32-разрядного процесса и взаимодействовать с вашей 64-битной программой через [вставьте здесь свой метод межоперационного процесса].

Вы можете использовать COM в качестве посредника, конечно; это неплохая идея.Но этот COM-посредник должен быть внепроцессным сервером (EXE), а не DLL.

Быстрый способ выполнить это, чтобы установить COM-помощник в качестве приложения COM + (компонентные службы). Скомпилируйте его как «32-битный», а не «AnyCPU». Убедитесь, что он установлен как «Сервер» не как «Библиотека». COM + предоставит 32-битный хост-процесс для него.

Независимо от того, можете ли вы позволить себе накладные расходы на запуск библиотеки, предназначенной для запуска в процессе через хост вне процесса, я не знаю. Это будет зависеть от того, что делает библиотека. В некоторых случаях это может быть просто невозможно (например, библиотеки, которые работают с аффинными ресурсами).

Если DLL должна запускаться внутри вашей программы, у вас есть только два варианта: a) Ваша программа должна быть скомпилирована как 32-разрядная. Или, б) вам нужно приобрести 64-битную версию библиотеки.

+0

Спасибо за ваш ответ. Я смог создать сервер COM +. Я импортировал свою 32-разрядную .NET-оболочку в Службы компонентов и на панели «Выполняющие процессы», я могу видеть мою службу (установленную как сервер). Но я не уверен, как мне обратиться к моему 64-битовому приложению. – user7176709

+0

Вы ссылаетесь на него так же, как раньше. COM заботится о различиях. –

+0

Я добавил 32-разрядную dll в качестве ссылки. Но я все равно получаю «Исключение BadImageFormat». Кажется, я пытаюсь напрямую вызвать DLL через свое приложение. Есть ли какое-либо свойство, которое мне нужно для установки службы COM? – user7176709

 Смежные вопросы

  • Нет связанных вопросов^_^