Как заставить DLL работать на разных версиях Windows? - PullRequest
6 голосов
/ 17 ноября 2009

Я собираю свою собственную DLL, состоящую из нескольких .o файлов. Один из файлов .o имеет функцию, которая вызывает SHLoadLibraryFromItem, которая поддерживается только в Windows 7. Эта функция никогда не вызывается, если только приложение, использующее DLL, не запущено в Windows 7. (Да, я уверен.)

Однако при запуске приложения в более старой версии Windows (скажем, XP) происходит сбой всего приложения при запуске с ошибкой «Указанная процедура не найдена». Хотя в ошибке не указано, какую процедуру не удалось найти, если я закомментирую вызов SHLoadLibraryFromItem, то все работает нормально.

Вопросы:

  1. Почему Windows пытается найти SHLoadLibraryFromItem, хотя она не вызывается в XP?
  2. Есть ли способ заставить Windows , а не сделать это, то есть найти SHLoadLibraryFromItem только при запуске Windows 7, т.е. какое-то ленивое связывание?
  3. Если нет, как лучше обойти это?

Единственный способ обойти это, я могу придумать:

  1. Используйте LoadLibrary, чтобы загрузить Windows DLL, в которой находится SHLoadLibraryFromItem, и используйте GetProcAddress, чтобы вручную получить адрес в указателе на функцию, и используйте указатель для вызова SHLoadLibraryFromItem вместо этого?
  2. Имеется две библиотеки DLL: одна содержит функции, поддерживаемые для Windows 7, которые будут загружаться только при работе в Windows 7.

Есть еще идеи? Я бы действительно предпочел ленивую привязку, как упоминалось выше.

Обновление

ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ, ЧТО Я НАСТОЯЩИЙ НАПИСАЛ. Я ясно заявил в первом абзаце, что SHLoadLibraryFromItem является , а не вызывается, если я не знаю, что приложение фактически работает в Windows 7.

Приложение аварийно завершает работу, только когда DLL загружена .

Ответы [ 2 ]

10 голосов
/ 17 ноября 2009

Компоновщик встраивает ссылку в ваши модули в каждую функцию API, которая используется. когда загрузчик Windows загружает ваш исполняемый файл и его модули, он должен «подключить» все вызовы в вашем коде к тем местам в памяти, где фактически загружены функции API. Если он не может их найти, он не будет продолжаться.

Использование LoadLibrary и GetProcAddress - это «стандартный» способ обойти эту проблему.

Использование двух DLL не поможет вам, потому что, пока одна из них не загружается, ваше приложение все равно не запустится. Вы можете обойти это, используя задержку загрузки, поместив весь код, который зависит от нового O / S, в отдельный модуль и обернув все вызовы этого модуля в обработчики исключений Win32 SEH (вы получаете исключение SEH при задержке загрузки не могу загрузить модуль). Преимущество состоит в том, что вы можете использовать «автоматическое» связывание без путаницы указателей на функции, но обработка исключений может быть довольно неприятной.

Эта статья объясняет немного и дает несколько примеров того, как аккуратно обернуть это.

2 голосов
/ 17 ноября 2009

Почему Windows пытается найти SHLoadLibraryFromItem, хотя это не вызывается на XP?

Windows разрешает ссылки, когда приложение загружается в память, а не когда выполняется вызов. Это называется «динамическое связывание» (в отличие от статического связывания с компоновщиком), но оно не является действительно динамическим. Следовательно, он не знает, будет ли конкретный метод вызываться во время выполнения или нет.

...