Я сделал расширение для Thunderbird. Он вызывает (через js-ctypes) написанную мной C++ DLL, которая, в свою очередь, ссылается на другие DLL, которые являются сборками, написанными на C# (существующий код). Если все файлы находятся в том же каталоге, что и исполняемый файл Thunderbird, все работает нормально.DLLs, ищущие библиотеки DLL
Теперь я переместил свои собственные файлы в каталог, который я сделал, чтобы отличать их от файлов Thunderbird. Каталог находится в пути, поэтому моя C++ DLL загружается при вызове. Однако, когда он начинает искать ссылочные сборки, он терпит неудачу.
Procmon показывает, что он ищет только ссылки в каталоге, в котором работает Thunderbird. Не только нет пути, он даже не смотрит в системные каталоги.
Что я могу сделать, чтобы загрузить мои DLL-файлы с его зависимостями, не вбрасывая все в собственную папку Thunderbird, которая, а также быть немного грязной, станет глупой, когда я переношу расширение на другие почтовые программы?
Редактировать: Добавлены выдержки из кода JS.
Из моей функции «init» есть;
this._kernel32 = ctypes.open("kernel32.dll");
this._setDLLDir = this._kernel32.declare("SetDllDirectoryA",
ctypes.default_abi,
ctypes.bool,
ctypes.char.ptr);
var ret;
ret = this._setDLLDir("C:\\Program Files (x86)\\AuthentStreamAttacher");
this._lib = ctypes.open("AttacherC.dll");
this._getStr = this._lib.declare("GetPackage",
ctypes.default_abi,
ctypes.char.ptr);
this._freeStr = this._lib.declare ("FreePackage", ctypes.default_abi, ctypes.void_t, ctypes.char.ptr);
ret = this._setDLLDir (null);
И где я фактически звоню _getStr и ищут зависимости AttacherC.dll, это is;
var ret;
ret = this._setDLLDir("C:\\Program Files (x86)\\AuthentStreamAttacher");
var str = this._getStr();
В каждом случае RET истинно (в соответствии с отладчиком на пошаговом), что предполагает вызов SetDllDirectory успешно. Поведение одинаково, независимо от того, использую ли я версию «A» или «W», в JS ничего нет, просто позвольте мне назвать «SetDllDirectory». Как будто каждый вызов происходит в его изолированном контексте, но в моей DLL «GetPackage» использует malloc для выделения некоторой памяти, которая затем должна быть освобождена в «FreePackage». FreePackage не генерирует исключения, предполагая, что выделенная память сохраняется между двумя вызовами.
Больше нестандартного поведения; если я укажу случайную строку как путь в SetDllDirectory («helloworld» в этом случае) ret is еще true. Таким образом, либо SetDllDirectory фактически не получает строку корректно через ctypes, либо не выполняет никаких проверок на ней.
Мое чувство теперь в том, что каждый вызов js-ctypes происходит в его собственном контексте, в некотором роде, и это расстраивает механизм поиска ассемблера .net, и единственный способ заставить это работать - иметь отдельную родную DLL с одной функцией, вызванной из javascript. Затем он вызывает SetDllDirectory и LoadLibrary в том же контексте, чтобы вызвать следующую оболочку в цепочке, которая затем вызывает мой реальный код C#. Мессия и кажется более склонным к тому, что происходит неправильно, поэтому я надеюсь, что кто-то придет и докажет, что я ошибаюсь?
Есть ли в руководстве по расширению ТБ что-нибудь сказать? Обычно вы вызываете 'SetDllDirectory'. Или используйте привязку времени загрузки. Последнее не очень весело. –
Не то, чтобы я видел. Я использую js-ctypes для вызова моей DLL из JavaScript, так как я потерпел неудачу с XPCOM. Документация js-ctypes охватывает поиск исходной DLL, но не ниже. –
Хорошо, тогда я думаю, у вас есть маршрут. У вас уже есть уровень JS, который загружает вашу DLL. Предположительно с вызовом 'LoadLibrary'. Поэтому добавьте вызов 'SetDllDirectory' непосредственно перед вызовом' LoadLibrary' в C++ DLL. Когда это вернется, добавьте второй вызов в 'SetDllDirectory', чтобы отменить изменение. –