Определите загруженный путь для DLL - PullRequest
3 голосов
/ 08 декабря 2010

Я хочу, чтобы мое приложение имело следующую структуру.

Exe
 |
 |----- DLL\DLL.dll, DLL\common.dll 
 |
 |----- DLL2\DLL2.dll, DLL2\common.dll

Мой EXE загрузит библиотеки DLL через

LoadLibraryEx(_T("DLL\\DLL.dll"), 0, 0);
LoadLibraryEx(_T("DLL2\\DLL2.dll"), 0, 0);

DLL.dll и DLL2.dll, с которыми будет связан проектcommon.dll через файл lib.Хотя будет * 2 различных версии common.dll.

Однако во время выполнения Exe ожидал от меня размещения common.dll в том же каталоге, что и Exe, но не в том же каталоге, что и DLL и DLL2.Есть ли способ, которым я могу решить эту проблему, имея возможность иметь вышеуказанную структуру каталогов.Тем не менее, все еще используйте lib для связи с DLL/DLL2 с common.

Ответы [ 3 ]

5 голосов
/ 08 декабря 2010
  1. Вы хотите загрузить две разные DLL с одинаковым именем (common.dll) в один и тот же процесс.

    Это кажется мне плохой идеей. Это действительно необходимо? Может ли один из них быть переименован?

  2. Гарантируя, что загружаемые вами DLL могут найти другие DLL, которых нет в пути поиска.

    (Если вы не загружали динамически DLL.dll и DLL2.dll, то я не уверен, что это будет. К счастью, я вижу, что вы. :))

    Если вы динамически загружаете DLL.dll и DLL2.dll (то есть используете LoadLibrary во время выполнения вместо ссылки на их .lib-файлы во время сборки), то вы можете заранее вызвать SetDllDirectory , чтобы явно добавьте каталоги DLL или DLL2 к пути поиска. Вы хотели бы иметь только один каталог в пути одновременно, чтобы убедиться, что был загружен правильный файл common.dll.

    Обратите внимание, что хорошей практикой, если она не нарушает плохо написанный компонент, вызывать SetDllDirectory ("") в начале вашей программы, чтобы удалить текущий рабочий каталог ( не программы каталог, не волнуйтесь) из пути поиска DLL. Это уменьшает проблемы безопасности, когда ваш код может быть обманут в загрузке DLL. Но также обратите внимание, что если вы сбрасываете путь поиска, вызывая SetDllDirectory (NULL), то вам необходимо впоследствии снова вызвать SetDllDirectory ("").

Итак, у вас будет такой код:

SetDllDirectory(NULL); // Reset.
SetDllDirectory(""); // Plug "binary planting" security hole. `
SetDllDirectory("C:\MyExePath\DLL");
LoadLibrary("C:\MyExePath\DLL\DLL.dll");

SetDllDirectory(NULL); // Reset.
SetDllDirectory(""); // Plug "binary planting" security hole.
SetDllDirectory("C:\MyExePath\DLL2");
LoadLibrary("C:\MyExePath\DLL2\DLL2.dll");

SetDllDirectory(NULL); // Reset.
SetDllDirectory(""); // Plug "binary planting" security hole.

(Не проверено, поэтому извиняюсь за любые ошибки или недостающие аргументы. Должно дать вам идею, хотя.)

(Вы должны вычислить C: \ MyExePath во время выполнения. Жесткое кодирование это было бы плохо, очевидно.)

(Я предполагаю, что DLL.dll и DLL2.dll неявно загружают свои common.dll. Если они загружают common.dll с помощью вызова LoadLibrary, то проблема еще проще: просто заставьте их рассчитать свои собственные пути и затем передать LoadLibrary полный путь к common.dll.)

Осторожно: SetDllDirectory влияет на весь ваш процесс. Если ваш процесс имеет несколько потоков, вы должны убедиться, что вызовы SetDllDirectory изолированы друг от друга, а также от чего-либо еще, что может вызвать вызов LoadLibrary. например Загружайте библиотеки при запуске, прежде чем создавать другой поток, если это возможно.

3 голосов
/ 08 декабря 2010

Это не сработает.Вы не можете связать "DLL2 \ DLL2.dll" с "DLL2 \ common.dll".DLL2.dll будет связан с "DLL \ common.dll".При загрузке «DLL2.dll» в памяти будет «common.dll», поэтому импорт DLL2.dll будет разрешен для этой DLL.1004 * не работают.Они влияют на то, как LoadLibrary находит "common.dll", но LoadLibrary("common.dll") вызывается только один раз для DLL \ DLL.dll

0 голосов
/ 08 декабря 2010

Хорошо, это действительно будет весело.

Основная вещь здесь заключается в том, что для загрузки DLL из других путей вы должны либо указать полный путь (при использовании LoadLibrary), либо развернуть переменную среды PATH, чтобы включить другие папки, содержащие ваши DLL. См. Setenv для получения подробной информации о том, как это сделать.

Простое решение - предоставить относительный путь к LoadLibrary. Но, похоже, вы связываете библиотеки DLL, и поэтому вы не можете применить это решение.

Проблема не в том, что в компоновке вашего проекта компоновщик времени выполнения будет использовать текущий рабочий каталог и переменную PATH. Поскольку вы, похоже, связываете библиотеку, нет никаких шансов, что вы можете «исправить» переменную PATH сразу после загрузки первой DLL и перед второй DLL. Остальное решение - переименовать общую DLL в нечто вроде common-1.dll и common-2.dll. Это также дает то преимущество, что вы можете поместить их все в один каталог.

(Если вы используете LoadLibrary в любом случае, просто исправьте переменную PATH ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...