Почему я могу получить исключение DLL не найден в Vista, но не XP?
У меня есть приложение, которое опирается на несколько управляемых библиотек. Эти управляемые библиотеки, в свою очередь, полагаются на некоторые неуправляемые библиотеки.
Когда я развертываю приложение на компьютере под управлением XP, оно работает нормально. Когда я делаю то же самое на машине с Vista, я получаю исключение DLL not found.
Я попробовал и проект установки VS2010, и установщик NSIS, чтобы выполнить развертывание, и оно одинаково в обоих случаях.
Почему это может случиться? Что я могу сделать, чтобы обойти это?
Обновление - Более подробная информация
- Оба установщика проверяют установку.NET 4.0 и устанавливают ее при необходимости.
- Компьютер с операционной системой Vista является 64 -разрядным, но установка, как и ожидалось, направляется в папку с программными файлами x86
- В обоих случаях у меня есть учетная запись администратора
- DLL хранятся в том же каталоге, что и исполняемый файл
- Насколько я могу судить, файлы копируются в нужный каталог
Обновление 2
- Полная ошибка на http://pastebin.ca/2046487
- DLL-файл Audiere.Net.dll, которая является одной из моих и является управляемой библиотекой.
Я не уверен, что эта ошибка означает, что он не может найти Audiere.Net.dll или он не может загрузить его, потому что не может быть найдена одна из его зависимостей.
Обновление 3 - Материал из Process Monitor
После запуска монитора процесса (спасибо Mehrdad!) Появляется несколько записей, которые не имеют статуса "УСПЕХ". Некоторые из них "ИМЯ НЕ НАЙДЕНО", а некоторые "ПУТЬ НЕ НАЙДЕН". (Он даже запрашивает файлы PDB, которые, как я думал, использовались только отладчиком.) Очень трудно понять, какие записи могут привести к фактической ошибке. Во всяком случае, я загрузил журнал (отфильтрованный, чтобы иметь соответствующий путь) на случай, если он что-то значит для кого-то.
Обновление 4 - добавлены файлы.pdb
Так что я немного отчаялся и включил файлы.pdb в вывод программы установки. Я думал, что это будет бесполезно, но на самом деле это привело к более полезной ошибке. Вместо того, чтобы просто сказать, что DLL не найдена, я теперь получаю исключение BadImageFormatException. Поискивая это говорит мне, что это распространенная проблема для двоичных файлов, скомпилированных на x86, но работающих на x64 (как на машине с Vista).
Предлагаемое решение - заставить его нацелиться на x86, но Audiere.Net.dll уже был. Может ли вина лежать на библиотеке, которую она упаковывает?
7 ответов
Решение оказалось довольно простым: одну из неуправляемых библиотек DLL нужно было перекомпилировать для x64.
Ключевые шаги:
- Проверьте монитор процесса на наличие вероятных источников ошибок. Внимательно посмотрите на сообщение об ошибке, которое Windows предлагает отправить при сбое приложения.
- Включите файлы.pdb для управляемых библиотек. Это привело к более информативным сообщениям об ошибках.
- Эти сообщения об ошибках не только указывали, какая управляемая библиотека вызывала ошибку, но и указывали на то, что это проблема x86/x64. (
BadImageFormatException
) - Следуя некоторым разумным советам, убедитесь, что все неуправляемые библиотеки ориентированы на x86. (Мои были, но это хорошо, чтобы быть уверенным.)
- Перекомпилируйте неуправляемые зависимости проблемной управляемой библиотеки на компьютере x64.
- Напишите скрипт установки, который копирует соответствующую (x86 или x64) версию DLL.
- Прибыль!
Особенности:
- Проблема, с которой я, казалось, была
Audiere.Net.dll
, но на самом деле был вызван проблемой сlibaudieresharpglue.dll
, - Я использую NSIS для установщиков. Чтобы выполнить специфическую для архитектуры DLL, я использовал заголовок x64.nsh.
Может быть, есть какое-то перенаправление, которое не позволяет вашему приложению установить в нужную папку?
Нам нужно немного больше деталей, но вы устанавливаете для пользователя или машины? Вы админ? Где обычно находится DLL?
Редактировать: попробуйте использовать Process Monitor, чтобы отслеживать, к какому файлу на самом деле обращаются.
Вы упоминаете, что Audiere.Net.dll предназначен для x86, но как насчет вашего исполняемого файла?
Очевидно, что вы можете перекомпилировать вашу программу или использовать Corflags (часть фреймворка), чтобы просмотреть текущие настройки вашего exe-файла.
Corflags ssd2.exe
Или установить или снять флаг
Corflags ssd2.exe /32BIT+
Corflags ssd2.exe /32BIT-
(Обратите внимание, что если ваше приложение подписано строгим именем, оно не будет работать, если вы не используете /Force для удаления подписи)
Если вы используете приложение.Net, на обоих компьютерах установлена соответствующая платформа?
Мы столкнулись с чем-то симулярным и обнаружили, что нам нужно загрузить пакет C++ Redistibuatable, чтобы программа могла работать на Windows 7 с использованием сторонних библиотек DLL.
Обычная причина в том, что рассматриваемая dll зависит от других dll, которых нет на компьютере с Vista (или, возможно, там, но не зарегистрировано).
Я помню, сталкивался с подобной проблемой с оболочкой SQLite. Источником проблемы, конечно же, является проблема 32/64 бита, и это тот же сценарий, что оболочка SQLite является управляемой оболочкой, что делает ее зависимой от процессора.
Я предполагаю, что хотя вы управляете библиотекой lib (Audiere.Net.dll) для 32-битной версии, основное приложение (ssd2.exe) - нет.
Папка установки определяется конфигурацией установки, но если проект приложения не настроен строго для компиляции как проект x86 (как правило, предназначенный для среды Any Cpu по умолчанию), приложение запускается как 64-битный процесс, независимо от путь установки. В этом легко убедиться, посмотрев процесс в диспетчере задач на 64-битной машине, у всех 32-битных процессов есть дополнительные *32 на 64-битной машине с Windows (на 32-битной машине их не будет).
РЕДАКТИРОВАТЬ: или более просто, глядя на свойства проекта->Build-> Platform Target:)
Во всяком случае - вы должны изменить настройки проекта для проекта, который собирает ssd2.exe для цели x86, и все должно быть в порядке.