В какой конфигурации мне нужно использовать внешнюю DLL в приложении WinForms? - PullRequest
3 голосов
/ 23 сентября 2011

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

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

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

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

Что бы это могло быть?

Обновление

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

Ответы [ 3 ]

1 голос
/ 05 октября 2011

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

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

  • Файл 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, включая * 1030.* 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 голосов
/ 04 октября 2011

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

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

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

    dumpbin / headers 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. Если он не добавляет папку, в которой установлена ​​dll, в% PATH%.

0 голосов
/ 30 сентября 2011

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

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

...