C # AppDomain загрузка (byte []) создает исключение FileLoadException (HResult 0x80131040 или ошибка манифеста)

1

У меня есть отдельное приложение.Net 4 для удаленного доступа к главному приложению (функции). Из-за недавних изменений он теперь ссылается на тот же файл, что и основное приложение. Это, конечно, предотвращает его копирование по новой dll, которая будет перезаписывать этот файл (в основном dll, который, помимо прочего, обрабатывает настройки - откуда мне нужно будет получить некоторые данные, которые предотвращают просто его не загружать). Просмотр через SO Я думаю, что мне удалось пройти дальше, но теперь попал в дорожный блок.

Я попытался загрузить DLL из ресурсов (не работает из-за того, что приложение находит более старый common.dll из каталога приложения, и если я загружаюсь из ресурсов, тогда существует конфликт типов между двумя разными версиями одной и той же DLL). Поскольку не существует способа изменить параметр DisallowApplicationBaseProbing для домена приложения по умолчанию (чтобы предотвратить загрузку более старой common.dll из каталога), я создал приложение запуска, которое запустит обновление для вновь созданного домена приложения с этим набором параметров. Чтобы не допустить, чтобы пусковая установка получала ссылки на файл настроек, ссылаясь на программу обновления, я включил их как ресурсы (если они ссылаются напрямую, то это приводит к тому, что файл загружается из каталога приложения и блокирует копирование файлов) которые вы можете увидеть ниже - у меня есть аналогичные блоки для других конфигураций.

<When Condition=" '$(Configuration)' == 'Debug' ">
  <ItemGroup>
    <EmbeddedResource Include="..\..\Libraries\Common\bin\Debug\Common.dll">
      <Link>Common.dll</Link>
    </EmbeddedResource>
    <EmbeddedResource Include="..\..\Deployment\Upgrader\bin\Debug\Upgrader.dll">
      <Link>Upgrader.dll</Link>
    </EmbeddedResource>
  </ItemGroup>
</When>

Насколько я вижу, правильная dll будет выбрана для ресурсов. В Launcher у меня есть следующий код (он находит данные, а ранее загрузил файл правильно - но теперь разбит).

        Console.WriteLine("Setting up AppDomain..");
        var setup = AppDomain.CurrentDomain.SetupInformation;
        setup.DisallowApplicationBaseProbing = true;

        createdDomain = AppDomain.CreateDomain("CorrectedCommonDomain", null, setup);
        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream("UpgraderLauncher.Common.dll"))
        {
            if (s == null)
            {
                Console.WriteLine("Could not load common.dll correctly!");
                throw new ArgumentNullException("Could not load internal common.dll resource.");
            }
            Console.WriteLine("Loading common.dll..");
            byte[] data = new byte[s.Length];
            s.Read(data, 0, data.Length);
            commonDllAssembly = createdDomain.Load(data);
            Console.WriteLine("Loading common.dll is done.");
        }

Возникает проблема: "createdDomain.Load (данные)"; часть, которые бросают FileLoadException (HResult 0x80131040 aka manifest error). Подробные сведения об исключениях приведены ниже.

Необработанное исключение типа "System.IO.FileLoadException" произошло в UpgraderLauncher.exe

Дополнительная информация: Не удалось загрузить файл или сборку "Common, Version = 1.0.5256.21424, Culture = neutral, PublicKeyToken = 86e85f643d1e5711" или одна из его зависимостей. Расположенное определение манифеста сборки не соответствует ссылке на сборку. (Исключение из HRESULT: 0x80131040)

После восстановления common.dll (а затем и запуска) обновляется версия DLL в сообщении об исключении. Как мне следует продолжить, и как проявление байт-загруженной dll будет отличаться от самого себя? (все файлы сильно подписаны.)

Теги:
dll
.net-4.0
updates

1 ответ

0
Лучший ответ

Хорошо, я решил это решить. Проблема заключалась в том, что сборка была загружена в оба домена (поскольку в сборке имеется ссылка на сборку, она также загружается в AppDomain по умолчанию, который вместо загрузки DLL, на который он был запрошен, вместо этого переходит к загрузке манифеста из старый файл из каталога, в котором находится пусковая установка, что заканчивается явным конфликтом между старым файлом и байтами, содержащимися в панели запуска). Чтобы разрешить ошибку в подобных ситуациях, вместо того, чтобы любой код загружал файлы в стандартном AppDomain, переместите загрузку в созданный AppDomain. Для этого сохраните байт [] в данных appdomain:

createdDomain.SetData("CommonDllAssembly", data);

А затем в коде, который выполняется в созданном домене:

byte[] bytes = AppDomain.CurrentDomain.GetData("CommonDllAssembly") as byte[];
commonDllAssembly = Assembly.Load(bytes);

Это предотвращает появление указанной ошибки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню