LoadLibrary не удалось с кодом ошибки 126, если приложение запускалось из варианта установки

У меня есть два приложения, которые устанавливаются в разных папках, позвольте называть его приложением A и B, A - это основное приложение, а B - модуль COM, A запустит B через COM API после запуска A, есть некоторые библиотеки DLL, которые необходимо загрузить с помощью B при запуске B, если я запускаю A двойным щелчком по ярлыку A, все в порядке, но если я устанавливаю A и запускаю A, проверяя параметр запуска A в последнем диалоговом окне установки, то запускается B, но одна из библиотек DLL не загружена с кодом ошибки 126 (ERROR_MOD_NOT_FOUND), если я выйду и перезапущу снова, дважды щелкнув ярлык, он снова заработает.

Уже выполняйте некоторые поисковые запросы, и, похоже, единственная разница между запуском с ярлыка и установкой - это текущий каталог, то есть, если запускается из варианта установки, так же, как запуск из папки пакета установщика с помощью cmd, например open cmd, переключитесь в папку пакета установщика, затем запустите приложение A с полным путем, я пробовал это, тоже хорошо работает.

Мой установочный пакет создается с помощью installshield.

Есть ли у кого-нибудь подсказки по этой проблеме?

  1. Уже пытайтесь переключить текущий каталог на путь установки A и B, оба не могут решить эту проблему.
  2. Уже попытка установить каталог dll на путь установки B, который также является путем сбойной библиотеки DLL, тоже не работает.
  3. Уже пытаюсь загрузить DLL с полным путем, тоже не удалось.
    //SetCurrentDirectory(L"C:\Program Files (x86)\install path of A"); <<<not work
    //SetCurrentDirectory(L"C:\Program Files (x86)\install paht of B");   <<<not work
    //SetDllDirectory(L"C:\Program Files (x86)\DLL path");   <<<not work
    //m_hLibrary = LoadLibrary((LPCWSTR)DLL full path);   //not work
    m_hLibrary = LoadLibrary((LPCWSTR)dllName.c_str());   //failed with error code 126

person Rick Zhang    schedule 29.03.2019    source источник
comment
Вы пытались избежать обратной или прямой косой черты? От L"C:\Program Files (x86)\DLL path" до L"C:\\Program Files (x86)\\DLL path"   -  person Zaiborg    schedule 29.03.2019
comment
Если у вас есть исходный код, не могли бы вы просто пройти через него в исходном коде? Установите точку останова в строке LoadLibrary, а затем посмотрите, что случилось со значениями переменных? Если нет, знакомы ли вы с использованием ProcMon.exe? Установите фильтр включения, чтобы включить все имена ваших exe-файлов, очистить все события, затем настроить запись, запустить exe и посмотреть, какие ошибки вы видите в списке событий файла? Я могу попытаться написать об этом, если вы не знакомы с этим. Элементарный пример использования здесь.   -  person Stein Åsmul    schedule 30.03.2019
comment
Отладка исполняемых файлов с помощью Visual Studio без исходного кода. А в древнем инструменте Dependency Walker есть функция профилирования, которая раньше работала, но в наши дни работает редко (меню профиля однажды открываешь exe). Если ничего другого, Options = ›Configure Module Search Order... =› Uncheck "Expand" and press "Default" = ›даст вам наиболее нормальный порядок поиска модулей (варьируется в каждой версии Windows).   -  person Stein Åsmul    schedule 30.03.2019
comment
Спасибо всем за ваш ответ.Просто имейте некоторое представление об этой проблеме, это должны быть проблемы с зависимостью, сбойная DLL зависит от нескольких библиотек DLL и одной из DLL, расположенных в другой папке, эта папка была добавлена ​​в путь к среде, но кажется, что эта папка не в пути поиска dll при запуске с установки, если скопировать эту dll в путь установки, она работает хорошо. Итак, теперь проблема в том, почему зависимый путь не добавлен в путь поиска. скоро добавлю больше деталей.   -  person Rick Zhang    schedule 02.04.2019
comment
Нажимаем @RickZhang, чтобы уведомить об ответе Урмана.   -  person Stein Åsmul    schedule 05.04.2019


Ответы (1)


Похоже, вы диагностировали симптомы. Их решение может быть непростым, поскольку по крайней мере некоторые версии InstallShield вызывают API-интерфейсы, которые снижают возможность загрузки неожиданных библиотек DLL до того, как будет создана папка приложения. Похоже, что эффекты этих вызовов переносятся на ваш процесс, когда вы запускаете его непосредственно из установщика.

Итак, во-первых, упрощенный вариант 1: удалите возможность запуска вашего приложения с последней страницы мастера. Пуф, проблема уходит. Но, наверное, кого-то это делает несчастным.

Вместо этого давайте попытаемся погрузиться в происходящее. В зависимости от конкретной версии InstallShield он может вызывать некоторую комбинацию API, но наиболее вероятным виновником является вызов SetDllDirectory(L"");. Согласно некоторым быстрое исследование, это должно повлиять только на неявно загруженные библиотеки DLL в дочерних процессах, но, похоже, это не тот сценарий, который вы описываете.

Вы пробовали отменить этот вызов, явно добавив каталог; вот мои рекомендуемые (но непроверенные) варианты 2 и 3:

  • Как описано в SetDllDirectory, позвоните SetDllDirectory(NULL), чтобы восстановить порядок поиска по умолчанию, или
  • Вызовите SetDllDirectory или AddDllDirectory, чтобы добавить свою папку, а затем вызовите _5 _
person Michael Urman    schedule 04.04.2019
comment
Наконец, решите эту проблему с помощью пути SetDllDirectory другой библиотеки DLL, который зависит от сбойной библиотеки DLL. На самом деле я добавил путь зависимой dll к системному пути, но, похоже, путь не работает, если запускать из установщика. - person Rick Zhang; 10.04.2019
comment
О, почему-то мне показалось, что вопрос указывает на то, что он работает с более ранней версией InstallShield, поэтому я сосредоточился на этой разнице. Но да, если вы изменяете PATH как часть установки, вам также необходимо распространить это на все, что запускается непосредственно из установщика. Иногда мы забываем проверить очевидное. Рад, что ты его получил! - person Michael Urman; 11.04.2019