Возникла ошибка BadImageFormatException с WcfSvcHost и хостом IIS WCF - PullRequest
4 голосов
/ 07 апреля 2009

Создание библиотеки служб WCF в Visual Studio 2008 в Vista x64 проблематично при обращении к библиотеке x86. Служба, которая вызывает 32-разрядную библиотеку DLL, должна иметь целевую платформу x86 для работы в 64-разрядной ОС. Когда вы делаете это, WcfSvcHost выдает исключение BadImageFormatException при попытке отладки службы. На MS Connect есть отчет об ошибке . Обходной путь, который я использовал, был coreflag WcfSvcHost как 32-битный .

Проблема с манифестом

Основная проблема, с которой я столкнулся, заключается в том, что эту стороннюю 32-битную DLL не удается загрузить с использованием определенных хостов WCF. Я получаю следующую ошибку, когда вызывается операция службы , использующая стороннюю DLL:

System.TypeInitializationException: инициализатор типа для выкинул исключение.

.ModuleLoadExceptionHandlerException: Вложенное исключение произошло после Основное исключение, вызвавшее C ++ модуль не загружается.

System.BadImageFormatException: модуль должен содержать сборочный манифест. (Исключение из HRESULT: 0x80131018)

NestedException:

Указатель недействителен. (Исключение из HRESULT: 0x80070006 (E_HANDLE))

Это исключение не вызывается при запуске WcfSvcHost, оно вызывается при вызове сервисной операции, которая ссылается на 32-битную DLL. Что очень интересно, размещение этого же сервиса с тем же app.config в консольном приложении не имеет исключений и работает отлично:

using (ServiceHost host = new ServiceHost (typeof (MsgBrokerService))) {
    host.Open ();
    Console.WriteLine ("running");
    Console.ReadLine ();

Это исключение возникает сразу после:

'WcfSvcHost.exe' (управляемый): загружен «C: \ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll '

Опять же, консольное приложение не имеет исключения и загружает ту же DLL:

'ConsoleApp.vshost.exe' (Управляется): нагруженный «C: \ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll '

См. Ответ от службы поддержки продуктов Microsoft .

Обновление № 1: и консольное приложение, и хост-процесс WcfSvcHost.exe выполняются в одном сеансе и вошли в систему (я). Я скопировал WcfSvcHost.exe в каталог службы, запустил вручную и получил тот же результат. Я также проверил журнал событий Windows для получения дополнительной информации и использовал sxstrace , но ничего не было зарегистрировано.

Запустив Process Explorer, я убедился, что между двумя процессами одинаковые:

  • Изображение: 32-разрядное
  • Текущий каталог
  • Пользователь / SID
  • Session
  • Безопасность (группы запрещены, привилегии отключены)

Запуск Process Monitor и настройка символов , я вижу, WcfSvcHost ищет следующий реестр и файлы, а консольный хост - нет. Process Monitor регистрирует много данных, и я не уверен, что я ищу: (.

HKLM \ SOFTWARE \ Microsoft \ Fusion \ PublisherPolicy \ Default \ policy.8.0.msvcm80__b03f5f7f11d50a3a C: \ Windows \ сборка \ GAC_32 \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a C: \ Windows \ сборка \ GAC_MSIL \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a C: \ Windows \ Assembly \ GAC \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a

Обновление № 2: это же исключение возникает, когда служба размещена в рабочей на IIS 6 / Windows Server 2003.

Обновление № 3: 32-разрядная сборка .NET стороннего производителя - это StreamBase API :

  • sbclient.dll (управляемый)
  • monitor.netmodule (управляемый)
  • dotnetapi.dll (неуправляемый)
  • pthreads-vc8.dll (неуправляемый)

Обновление № 4: добавлены манифесты без успеха:

  1. Проверено, что dotnetapi.dll и pthreads-vc8.dll имеют RT_MANIFEST. Сборка sbclient.dll .NET не имеет манифеста
  2. Удален sbclient.dll из GAC
  3. Зарегистрированный sbclient.dll для проверки пропуска
  4. Добавлен манифест через mt.exe как для sbclient.dll, так и для monitor.netmodule
  5. Добавлен проверенный манифест и что ожидаемые файлы были загружены во время тестирования (через Visual Studio - окно отладочных модулей)
  6. Та же исключительная ситуация BadImageFormatException создается в BackgroundWorker.OnDoWork (), и в стеке вызовов отображается вызов dotnetapi.dll ... DefaultDomain.Initalize ().

Я проверил, что msvcm80.dll не имеет манифеста, я считаю, что это единственный загруженный файл, у которого нет манифеста:)

Интересная находка

Когда я загружаю модуль monitor.net в Отражатель , он говорит:

'monitor.netmodule' не содержит сборочный манифест.

Несмотря на то, что он отображает ошибку, Reflector все еще может разобрать управляемый код.

Ответы [ 7 ]

4 голосов
/ 01 декабря 2010

немного поздно, но вы также можете изменить настройку пула приложений «Включить 32-битные приложения» на true в дополнительных настройках.

2 голосов
/ 03 июня 2009

Служба поддержки продуктов Майкрософт решила этот вопрос: это сделано специально. Неуправляемый код не загружается в домен приложения по умолчанию при использовании WcfSvcHost или узла IIS WCF.

Чистое изображение будет использовать версию CLR библиотека времени выполнения C. Тем не менее ЭЛТ не поддается проверке, поэтому вы не можете используйте CRT при компиляции с / CLR: сейф. Для получения дополнительной информации см. C Библиотеки времени выполнения.

http://msdn.microsoft.com/en-us/library/k8d11d4s.aspx

0 голосов
/ 20 апреля 2018

столкнулся с этим вопросом сам. Я нашел полезный пост . Как отмечалось в других постах, Microsoft заявила, что это сделано специально В основном вам нужно:

  1. Найдите свою версию WcfSvcHost.exe. (для меня и визуальной студии 2017: C: \ Program Files (x86) \ Microsoft Visual Студия \ 2017 \ Professional \ Common7 \ IDE)

  2. Запуск командной строки разработчика

  3. Выполнить cmd: copy C:\SourcePath\WcfSvcHost.exe C:\DestinationPath\WcfSvcHost32.exe (назначение не имеет значения)

  4. cmd: corflags /32BIT+ /Force WcfSvcHost32.exe (может потребоваться перейти к DestinationPath

  5. В Visual Studio откройте свойства проекта WCF> вкладка «Отладка»> «Запустить внешнюю программу»: C:\DestinationPath\WcfSvcHost32.exe

  6. Также добавьте аргументы командной строки:

    / обслуживание: MyWCFProjectName.dll /config:MyWCFProjectName.dll.config

    Примечание: вам не нужно использовать ($ProjectDir) здесь

  7. Запустите приложение. Теперь вы можете запускать WcfServiceHost.exe отдельно.

  8. При необходимости перейдите к решению> Установить проекты запуска> Несколько проектов запуска> Выберите проект Wcf и проект клиента.

0 голосов
/ 18 мая 2012

Это может показаться немного глупым; но убедитесь, что ваша служба работает в правильном пуле приложений.

0 голосов
/ 19 апреля 2009

Не могли бы вы вручную добавить манифест в эту DLL, используя файл mt.exe?

MSDN Статья по использованию mt.exe

0 голосов
/ 16 апреля 2009

Видите ли вы что-то особенное в окне просмотра событий?.
В Vista, если есть явная проблема, вы увидите ее след в средстве просмотра событий, он скажет вам использовать SxsTrace .

0 голосов
/ 15 апреля 2009

Я не могу предоставить объяснение ошибки, только мое первоначальное подозрение, что существует разница в разрешениях между контекстом, в котором ваш код запускается как служба, и контекстом, в котором он запускается, когда вы помещаете его в консольное приложение. , E_HANDLE HRESULT - моя подсказка. Предполагая, что вы запускаете консольное приложение как вошедший в систему пользователь, вы можете попытаться настроить службу так, чтобы она также запускалась от имени этого пользователя. Если он работает в этой конфигурации, вы можете попытаться сузить необходимый ресурс, недоступный в случае сбоя.

Я могу предложить обходной путь. Если есть какая-то странность рассматриваемой библиотеки DLL, которая мешает ей работать в размещенной службе, вы можете использовать жертвенный процесс, названный так потому, что он обычно используется для изоляции DLL, которая часто выходит из строя. Вкратце, вы создаете прокси-программу, единственная цель которой - загружать и вызывать DLL от имени вашего основного процесса, используя именованные каналы или какой-либо другой метод IPC для передачи запросов и результатов. В случае сбоя DLL вы запускаете новый экземпляр прокси-программы. В вашем случае будет иметь дополнительное преимущество, что только программа-обертка должна быть 32-битной.

...