2011-09-23 6 views
3

Я работаю с внешней DLL, чтобы использовать устройство OCR, используя написанную мной обертку. Я сделал тесты на обертке, и он отлично работает. Но когда я использую проект WinForms для использования класса клиента оболочки (находящегося в другом проекте), возникает ошибка при вызове методов C#, импортированных из DLL (с ​​использованием [DLLImport(...)]), в которых говорится, что DLL не зарегистрирована.Какую конфигурацию мне нужно использовать внешнюю DLL в приложении WinForms?

Ошибка говорит:

"Функция библиотеки DLL не найден Проверьте реестра путь установки."

Все исполнения были выполнены в режиме отладки. Я сравнивал конфигурацию обоих проектов. Самое важное отличие состоит в том, что проект тестирования ориентирован на любое приложение с процессором и WinForms, которое указывает только на x86.

Что это может быть?

Обновления

  1. Я пытался зарегистрировать DLL с помощью Regsvr32.exe, но это не сработало. Я думал об использовании Gacutil.exe, но для удаления всех фреймворков за рамки .NET. 1.1 ...
  2. Мне было интересно ... в тестовой среде, вероятно, все работает хорошо, потому что тестовая среда имеет свои DLL-файлы или исполняемые файлы (или что-то в этом роде), полностью зарегистрированных в Windows, поэтому это доверенные DLL. Возможно, что отлаженные сгенерированные DLL не доверяются окнами, и поэтому возникает эта проблема?
  3. Я создал форму в том же тревожном проекте, а затем я вызываю OCRWrapper с кнопки, которую я добавил к ней. OCR работает!. К сожалению, сложно переписать первую форму, потому что мы потратили на нее много часов; так что мне все еще интересно, что мне нужно изменить в тревожной форме ...
  4. Я начал с нуля разработку формы с нуля и добавил все связанные с ней компоненты; все работало хорошо, OCR внимательно прочитало все данные. Когда я загрузил поле со списком, используя вызов ObjectContext, и ошибка появилась снова ... Я использую инфраструктуру сущности, связанную с Oracle.
+0

Вы работаете на 64-битной системе? – stuartd

+0

@StuartDunkeld Intel Core 2 Duo ... Я полагаю, что это 64-битная система, но, хотя я и сделал это в google, я не уверен ... – JPCF

+0

@HansPassant исключение не из Visual Studio. .. когда я вызываю метод из OCR (используя метод '[DLLImport]' отмеченный метод), возвращенное сообщение об ошибке - '' Функция библиотеки DLL не найдена. Проверьте путь установки реестра. ". – JPCF

ответ

1

У меня есть теория.

Давайте представим себе следующую ситуацию:

  • ocr.dll зависит от какой-либо другой родной DLL, позволяет называть его other.dll [A].
    • В случае, если это статическая зависимость, вы увидите ее через Dependency Walker.
    • Если его динамика, вы можете использовать Sysinternals Process Explorer для контроля загрузки DLL в рабочем проекте тестирования во время выполнения.
  • Ваш провайдер ADO.NET использует собственные библиотеки DLL под капотом (это, конечно, верно для ODP.NET), которые зависят от other.dll [B], что случается иметь то же самое имя, но на самом деле является другая DLL (или, по крайней мере, другая версия) по сравнению с other.dll [A].

Затем, во время выполнения, это может произойти:

  • При подключении к базе данных, поставщик ADO.NET динамически загружает свои собственные библиотеки DLL, в том числе other.dll [B] ,
  • Затем вы пытаетесь вызвать функцию из OCR DLL. P/Invoke пытается загрузить DLL OCR динамически и успешно, но other.dll [B] уже загружен и ocr.dll пытается использовать некоторую функцию из него, а не other.dll [A], где он действительно существует.

Добро пожаловать в DLL-ад. Так что ты можешь сделать?

  • Попробуйте изменить порядок вызовов ocr.dll и поставщику ADO.NET, чтобы увидеть что-либо изменение. Если вам (очень) повезло, other.dll [A] действительно может быть более новой версией, которая по-прежнему совместима с обратным адресом с other.dll [B], и все, что волнует волшебство, начинает работать.
  • Попробуйте использовать другую версию поставщика ADO.NET.
  • Попробуйте использовать другой поставщик ADO.NET.
  • Попробуйте получить статически связанную ocr.dll от вашего поставщика (т. Е. Нет зависимости от времени выполнения от other.dll [A]).
0

Таким образом, вызов в DLL работает с одной кнопкой, но он не работает из сложной формы. Я бы сказал, что происходит неопределенное поведение. Вопрос остается в том, что это вы, который неправильно написал маршаллинг, или это DLL, которая плохо написана.

Поскольку у нас нет доступа к исходному коду DLL, возможно, вы можете опубликовать прототип функции и все соответствующие определения структур и строку DllImport, которую вы написали для нее?

+0

Я не думаю, что ошибка лежит на маршаллинге, потому что OCR не удается выполнить _only_ при вызове из определенной формы ... но посмотрите: '[DllImport («aDll.dll»)] private static extern uint aMethod() ',' [DllImport («aDll.dll», CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] частная статическая внешняя строка aMethod2 (ulong aParameter); ' , '[DllImport (« aDll.dll », CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]' , 'private static unsafe extern ulong aMethod3 (ref IntPtr aParameter, ref IntPtr anotherParameter, ref IntPtr afterTheLastParameter);'. – JPCF

+0

Sice Я работаю с частной dll для обеспечения безопасности. Мне не разрешено раскрывать конкретные детали. Но подписи - это те, которые я написал [здесь] (http://stackoverflow.com/questions/7515798/problem-at-marshalling-a-standard-c-string-to-ac-string), [здесь] (http://stackoverflow.com/questions/7423376/how-can-i-write-a-signature-on-c-for-a-wrapped-c-method-having-double-indirect) и [здесь] (http://stackoverflow.com/questions/7410382/how-can-i-write-a-signature-on-c-for-a-wrapped-c-method-having-a-pointer-to-a) – JPCF

+0

Что вы делаете это сложно ... Я только что видел другие вопросы, и я не уверен, что они абсолютно правы.Мне нужно будет увидеть прототипы C этих функций и, возможно, некоторые примеры кода C, использующие их. Прототипа не всегда достаточно, чтобы написать правильный маршалл, вам нужна информация о поведении. – rodrigo

0

Google не может найти это сообщение об ошибке, что означает (не обязательно, хотя :)) это не системное сообщение, а пользовательское, исходящее из кода в dll. Так что dll делает что-то изворотливое. Наверное, он пытается удвоить отправку вашего вызова на другую функцию внутри.

Несколько вещей, которые я предлагаю вам попробовать:

  • Выполнить конфигурацию x86. В свойствах проекта -> вкладка Build установите платформу для x86. это предполагает, что dll является dll x86.

    DUMPBIN/заголовки orc.dll

    File Type: DLL 
        FILE HEADER VALUES 
    
           14C machine (**x86**) 
            4 number of sections 
          4CE7B6FC time date stamp Sat Nov 20 11:54:36 2010 
            0 file pointer to symbol table 
            0 number of symbols 
            E0 size of optional header 
           2102 characteristics 
             Executable 
             32 bit word machine 
             DLL 
    

Эта команда должна сказать вам разрядность. В случае, если это 64-разрядный запуск 64-битной конфигурации, но я уверен, что это 32 бит.

  • Не включайте dll в проект. Наверное, ты это делаешь. Убедитесь, что dll находится в папке, которая находится в переменной среды% PATH%. При запуске этого в командной строке:

где ocr.dll

должен сказать вам, где длл есть. Если он не добавляет папку, в которой dll устанавливается в% PATH%.

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