Мой вопрос не совсем такой же, как Вот этот (это не теоретически, есть только основной поток без цикла сообщений, InitInstance и ExitInstance не подходят).
Я использую консольное приложение без цикла сообщений; это приложение загружает exe-файл с функцией LoadLibrary, чтобы можно было использовать свои экспортированные функции. Плохая новость: функция DllMain исполняемого файла не вызывается (и я проверил таблицы символов, используя файл def, DllMain отображается правильно); документ говорит он вызывается, если загруженный модуль является DLL (очень плохо).
Каковы условия (если они существуют), которые могут привести к выполнению функции exe DllMain при вызове LoadLibrary (и, возможно, снова при вызове FreeLibrary)?
С наилучшими пожеланиями





Наиболее очевидным условием является то, что вызывающий LoadLibrary () процесс явно получает GetProcAddress ("DllMain"), а затем вызывает его.
Завершая хороший ответ MSalters:
Итак, вызовите «поддельный» DllMain с помощью DLL_XXX_ATTACH сразу после LoadLibrary и с помощью DLL_XXX_DETACH непосредственно перед FreeLibrary и сделайте вручную остальные вызовы.
Другая следующая реализация - это создание и загрузка интерфейсной DLL, которая могла бы автоматически выполнять обратный вызов EXE на своем поддельном DllMain (я не знаю, может ли это сработать); но в ряде случаев это может быть сложнее, чем просто вручную вызвать поддельный DllMain. (невозможно LoadLibrary в DllMain)
Условия следующие:
1) Загружаемый двоичный файл был скомпилирован как DLL (при использовании gcc / ld это означает использование опции --shared; если вы используете --shared, результирующий файл будет dll и не будет запускаться, см. Ниже)
2) IMAGE_FILE_DLL устанавливается в заголовке PE файла загружаемого двоичного файла. Если он установлен, файл является dll, и компоновщик Windows вызовет для вас свою функцию DllMain(), когда он связывает этот файл с вашей программой (не имеет значения, как он связан - LoadLibrary() во время выполнения или -llibraryname во время компиляции). Для этого файл также должен удовлетворять (1). Но с этим флагом загружаемый двоичный файл не будет запускаться. Если IMAGE_FILE_DLL не установлен, DllMain() не будет вызываться при загрузке файла в вашу программу.
Компиляция dll с помощью --shared с последующим удалением IMAGE_FILE_DLL из заголовка вручную (то есть с помощью шестнадцатеричного редактора) не будет работать - когда вы запустите его, будет выполняться только DllMain(), а номер fdwReason будет неопределенным (0x28ffd4 на моей машине).
Обновлять
Все файлы DLL и EXE в Windows являются файлами PE, разница в том, как они связаны и какие флаги установлены в их заголовках. Вот почему я пишу file being loaded, а не dll being loaded.
В последнем абзаце также описан сценарий, в котором вы компилируете файл как dll, а затем превращаете его в exe, изменяя его заголовок. Не работает.
Именование не имеет к этому никакого отношения (вы можете выбрать любое имя, и, немного подправив pexports + dlltool, вы можете создать библиотеку импорта для файла .exe и иметь возможность связать ее как -lexenamewithoutextension
Чтобы уточнить:
--shared:
IMAGE_FILE_DLL не будет установлен в нем, он будет работоспособен, но DllMain () НЕ будет вызываться при его связывании.--shared:
IMAGE_FILE_DLL будет установлен в нем, он НЕ будет запускаться, но DllMain () будет вызываться при его связывании.--shared, то включите в нем флаг IMAGE_FILE_DLL вручную:
--shared, то отключите в нем флаг IMAGE_FILE_DLL вручную:
В вопросе конкретно упоминается загрузка исполняемого файла (.exe) с использованием LoadLibrary, а не DLL. Пожалуйста, перечитайте вопрос.
Ваше редактирование ничего не меняет. Нигде в вопросе не говорится, что файл был скомпилирован / связан как что-либо, кроме файла .exe. (Исполняемые файлы в Windows могут экспортировать функции так же, как DLL, без необходимости сначала компилировать их как DLL.)
Был задан вопрос: «Каковы условия (если они существуют), которые могут привести к выполнению функции exe DllMain при вызове LoadLibrary (и, возможно, снова при вызове FreeLibrary)?» Вот на что я отвечаю. Для автоматического вызова DllMain () необходимо скомпилировать двоичный файл как разделяемую библиотеку и установить в нем флаг DLL.
Вы все еще упустили мою точку зрения. :-) Если у вас есть .EXE, DLLMain не будет вызываться автоматически. Конечно, у вас может быть функция с именем DLLMain, но это все равно, что назвать класс Car и ожидать, что вы сможете использовать его для доступа к приложению вашего врача. В .EXE нет функции auto-callable DLLMain(), поэтому вы не можете заставить ее автоматически вызываться при загрузке .EXE с LoadLibrary().
Вы говорите, что он упустил вашу точку зрения, но затем вы переходите к заявлению, которое в основном покрывается его ответом. Ответ от LRN, похоже, является надмножеством большей части вашего утверждения. Та часть, которой у него не было, была Зачем, она работает именно так, хотя Мартин упоминает об этом в своем ответе.
Действительно, имя функции "DllMain" полностью игнорируется Windows (в старой документации Windows API для Windows NT 3.x это прямо указывалось).
Когда загружается DLL, вызывается не функция DllMain (), а функция, расположенная в точке входа в файл.
Конечно, компоновщик создаст файл DLL таким образом, чтобы DllMain () была этой функцией.
Однако для файлов EXE функция входа (которая вызовет WinMain ()) находится в точке входа.
Таким образом, очевидно, что Windows не может вызвать эту функцию при загрузке EXE-файла как DLL.
Вы не можете вызвать LoadLibrary ("your.exe") из DllMain в вашей вспомогательной DLL - часть длинного списка вещей, которые вы не можете там делать. Это делает вашу вспомогательную DLL довольно сложной в использовании; это не может быть просто обертка / экспедитор,