2009-04-07 59 views
4

在Vista x64上的Visual Studio 2008中创建WCF服务库在引用x86 DLL时很麻烦。调用32位DLL的服务需要x86的平台目标在64位操作系统上运行。当您这样做时,WcfSvcHost在您尝试调试服务时会引发BadImageFormatException。 MS连接上有一个bug report。我使用的解决方法是coreflag WcfSvcHost as 32-bitBadImageFormatException遇到WcfSvcHost和IIS WCF主机

清单问题

我已经运行到这是第三方的原生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'

此外,在控制台应用程序没有一个例外? n和加载同一个DLL:

'ConsoleApp.vshost.exe'(管理): 加载 “C:\ WINDOWS \ WinSxS文件\ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll “

请参阅回答from Microsoft Product Support

更新#1:控制台应用程序和WcfSvcHost.exe主机进程都在相同的会话和登录用户(我)下运行。我复制了WcfSvcHost。exe文件到服务目录,手动启动并经历相同的结果。我还检查了Windows事件日志以获取更多信息,并使用了sxstrace,但没有记录任何内容。

运行进程资源管理器,我已验证以下是两个过程之间的相同:

  • 图片:32位
  • 当前目录
  • 用户/ SID
  • 会话
  • 安全性(拒绝组别,禁用特权)

Running Process Monitor和configuring symbols,我看到WcfSvcHost查找以下注册表和文件,而控制台主机却没有。 进程监视器记录了大量的数据,我不知道我在寻找:(

HKLM \ SOFTWARE \微软\融合\ 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 \装配\ GAC \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a

更新#2:此服务在生产中托管的服务为时也会发生此异常上IIS 6/Windows Server 2003的

更新#3:第三方32位.NET组件是StreamBase API

  • sbclient.dll(管理)
  • monitor.netmodule(管理)
  • dotnetapi.dll(非托管)
  • 并行线程,vc8.dll(非托管)

更新#4:新增体现没有成功:

  1. 验证dotnetapi.dll和pthreads-vc8.dll有RT_MANIFEST。该sbclient.dll .NET程序集没有一个清单
  2. 从验证跳过
  3. 增加了一个清单的GAC
  4. 注册sbclient.dll通过mt.exe sbclient.dll删除这两个sbclient.dll和monitor.netmodule
  5. 已添加已验证的清单,并且测试期间加载了预期的文件(通过Visual Studio - 调试模块窗口)
  6. 在BackgroundWorker.OnDoWork()下引发了相同的BadImageFormatException,并且调用堆栈显示对dotnetapi.dll ... DefaultDomain.Initalize()。

我已经验证了msvcm80。DLL没有一个清单,我认为这是唯一的文件加载不具有清单:)

有趣的发现

当我在Reflector加载monitor.netmodule,它说:

'monitor.netmodule'不包含 程序集清单。

即使它显示错误,Reflector仍然能够反汇编托管代码。

+1

什么是第三方32位DLL,它有什么作用? – 2009-04-18 05:51:05

+0

StreamBase - 以上详细信息 – 2009-04-20 16:52:53

回答

1

Microsoft产品支持已经解决了这个问题:这是由设计。使用WcfSvcHost或IIS WCF主机时,未托管的代码不会加载到默认的AppDomain中。

纯图像将使用C运行时库的CLR版本 。但是, CRT不可验证,所以在编译时使用CRT时不能使用 /clr:safe。有关更多信息,请参阅C 运行时库。

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

0

我无法提供错误的解释,只有我最初的怀疑是,在将代码作为服务运行的上下文与将代码放置在控制台中时运行的上下文之间存在权限差异应用。 E_HANDLE HRESULT是我的线索。假设您以您登录的用户身份运行控制台应用程序,您可以尝试配置该服务以便以该用户身份启动。如果它在该配置中工作,那么您可以尝试缩小失败时所需的资源不可用的范围。

我可以建议一种解决方法。如果有问题的DLL可能会阻止它在托管服务中工作,那么可以采用牺牲性进程方法,因为它通常用于隔离经常崩溃的DLL。简而言之,您创建一个代理程序,其唯一目的是代表您的主进程加载和调用DLL,使用命名管道或其他IPC方法传递请求和结果。如果DLL崩溃,则启动代理程序的新实例。在你的情况下,它会有额外的好处,只有包装程序需要32位。

0

你在事件查看器中看到什么特别的东西吗?
在Vista中如果出现清单问题,您会在事件查看器中看到它的痕迹,它会告诉您使用SxsTrace

4

有点晚了,但你还可以更改应用程序池设置“启用32位应用程序”,在高级设置为true。

0

这可能看起来有点愚蠢;但请确保您的服务正在正确的应用程序池中运行。