Сборка COM-взаимодействия не находит собственной (.Net) зависимости при вызове из Vb


У меня есть сборка COM-взаимодействия C#, которую я вызываю из приложения Visual Basic 6. Эта сборка делает HTTP-запросы для отправки и получения JSON.

Сборка прекрасно работает при тестировании с помощью тестового клиента C#.

Однако при использовании его из приложения VB6 возвращается следующая ошибка:

"не удалось загрузить файл или сборку' Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' или одна из его зависимостей. То система не может найти указанный файл."

Newtonsoft.Json.dll находится в той же папке, что и библиотека DLL COM-Interop (TLB).

Нужно ли явно загружать Newtonsoft.Json.dll? Или, может быть, помещен в GAC?

2 3

2 ответа:

Ганс дал отличное объяснение, Почему это происходит. Позвольте мне предложить обходной путь для выполнения этой работы Без необходимости регистрировать DLL Json в GAC или копировать ее в каталог VB6 EXE.

В вашей COM-видимой библиотеке C# мы можем попросить среду выполнения .NET искать библиотеку DLL Json в каталоге библиотеки C# вместо "обычных" путей. Мы делаем это, прикрепляя наш собственный обработчик к событию AssemblyResolve:

AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
{
    // We only want this workaround for one particular DLL
    if (e.Name != "Newtonsoft.Json")
        return null;

    var myLibraryFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var path = Path.Combine(myLibraryFolder, "Newtonsoft.Json.dll");

    return Assembly.LoadFrom(path);
};

Заметки об этом обходной путь:

  • Этот код работает только в том случае, если он выполняется в вашей библиотеке C# , прежде чем делать что-либо, что может вызвать дрожание для загрузки библиотеки JSON. Например, ни ваша библиотека, ни любая другая библиотека .NET в процессе VB6 не должны вызывать метод, ссылающийся на типы из библиотеки JSON, прежде чем этот код будет выполнен.

  • Вы изменяете поведение всего процесса, а не только вашей библиотеки. Если ваш процесс VB6 использует другую библиотеку, использующую JSON, ваш "редирект" также влияет на другую библиотеку.

Это стандартная проблема DLL Hell, она вызвана использованием параметра / codepage для Regasm.exe. Или, чаще всего, флажок Project > Properties > Build tab > "Register for COM interop". Оба делают одно и то же, они записывают путь к DLL в реестр. Это очень хороший вариант для использования, когда вы заняты разработкой и тестированием проекта, он позволяет избежать необходимости повторно регистрировать DLL в GAC каждый раз, когда вы вносите изменения.

Но то, что он делает Не , это помогите CLR найти любые зависимости. Обычные правила зондирования остаются в силе, он ищет имя приложения.exe.конфигурационный файл в каталоге, где хранится исполняемый файл. И сначала заглядывает в GAC, затем в путь EXE для зависимостей. Конфигурация остается под контролем обычной жертвы DLL ада, кто бы ни должен поддерживать EXE. Часто конечный пользователь. Таким образом, явно, он не ищет в каталоге, где хранится ваша [ComVisible] DLL.

Это мягкий вид DLL Черт возьми, просто досье на файл, который не нашли. Гораздо мягче, чем неприятный вид, находя файл с правильным именем, но неправильной версией. Вообще сильная проблема с Newtonsoft.формат JSON.dll, есть около 35 версий в дикой природе. Имея так много версий, и это такая популярная библиотека также порождает другой вид гадости, программа использует другой COM-сервер, который также использует DLL. Но почти неизбежно другая версия. Как правило, это происходит задолго до того, как вы объявили свой проект законченный. Один из них проиграет, 50 на 50 шансов, что это ты. 100% шансов для конечного пользователя.

Да, GAC решает эту проблему. Каждая библиотека получает версию, которую они просят. В идеале Newtonsoft решила бы эту проблему для вас с помощью установщика, который развертывает DLL в GAC. Но это не то обязательство, которое авторы библиотек с открытым исходным кодом когда-либо хотели бы предоставить. Они хотят (и нуждаются) сделать это вашей проблемой. Microsoft делает это, но у них также есть Центр обновления Windows, чтобы гарантировать эта критическая ошибка и исправления безопасности будут развернуты. И пусть большое количество людей работает над тем, чтобы любые новые версии всегда были обратно совместимы с исходным релизом, поэтому номер версии не должен меняться.

Обратите внимание, что Вы можете воспользоваться обязательствами Microsoft. Для выполнения этой работы можно также использовать классы DataContractJsonSerializer и JavascriptSerializer. Часть структуры, они редко ошибаются.

Тем временем, сделайте имейте в виду, что это Просто проблема с файлом, который не найден. Вам не нужно использовать GAC на вашей машине разработки, и лучше, если вы этого не сделаете, так же легко скопировать файл в нужное место, чтобы сохранить CLR счастливым. Это тот же каталог, что и ваша тестовая программа VB6. И, дополнительная причуда с VB6, в C:\Program файлы (x86)\Visual Studio\VB6, если вы хотите использовать отладчик VB6. Используйте GAC при развертывании.