Creating a WCF service library in Visual Studio 2008 on Vista x64 is problematic when accessing the x86 DLL. The service that calls the 32-bit DLL must have the x86 target platform to run on the 64-bit OS. When you do this, WcfSvcHost throws a BadImageFormatException when trying to debug a service. There is an error report in the MS connection. The workaround I used was in the coreflag WcfSvcHost as 32-bit .
Manifest issue
The main problem that I encountered is that this 32-bit third-party DLL does not load using specific WCF hosts. I get the following error when a service operation that uses a third-party DLL is called :
System.TypeInitializationException: type initializer for '' made an exception.
.ModuleLoadExceptionHandlerException: A nested exception occurred after a primary exception that caused the C ++ module to not load.
System.BadImageFormatException: The module should have contained a collection manifest. (Exception from HRESULT: 0x80131018)
NestedException:
Invalid handle. (Exception from HRESULT: 0x80070006 (E_HANDLE))
This exception does not occur when WcfSvcHost is started, it occurs when a service operation is called that references a 32-bit DLL. Which is very interesting, if you have the same service with the same app.config in the console application, there are no exceptions and works fine:
using (ServiceHost host = new ServiceHost (typeof (MsgBrokerService))) { host.Open (); Console.WriteLine ("running"); Console.ReadLine ();
This exception occurs immediately after:
'WcfSvcHost.exe' (managed): loaded 'C: \ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll'
Again, the console application has no exception and loads the same DLL:
'ConsoleApp.vshost.exe' (managed): loaded 'C: \ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll'
See the answer from Microsoft Product Support Services .
Update # 1: both the console application and the WcfSvcHost.exe host process work under the same session and the logged in user (me). I copied WcfSvcHost.exe to the service directory, started manually, and got the same result. I also checked the Windows event log for more information and used sxstrace, but nothing was logged.
Starting the process handler, I checked that between the two processes the same thing:
- Image: 32-bit
- Current directory
- User / SID
- Session
- Security (groups are denied, privileges are disabled)
Running Process Monitor and character settings , I see that WcfSvcHost is looking for the following registry and files, but the console host is not. Process Monitor logs a lot of data, and I'm not sure what I'm looking for: (.
HKLM \ SOFTWARE \ Microsoft \ Fusion \ PublisherPolicy \ Default \ policy.8.0.msvcm80__b03f5f7f11d50a3a C: \ Windows \ build \ GAC_32 \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a C: \ Windows \ build \ Gaf507505.50f30.50fgfs Windows \ Assembly \ GAC \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a
Update # 2: The same exception occurs when a service is hosted in production on IIS 6 / Windows Server 2003.
Update No. 3: 32-bit .NET assembly of the 3rd-party version - StreamBase API :
- sbclient.dll (managed)
- monitor.netmodule (managed)
- dotnetapi.dll (unmanaged)
- pthreads-vc8.dll (unmanaged)
Update # 4: Added manifestos without success:
- Checked that dotnetapi.dll and pthreads-vc8.dll have RT_MANIFEST. The sbclient.dll.NET compilation did not have a manifest
- Removed sbclient.dll from GAC
- Registered sbclient.dll for pass checks
- Added manifest using mt.exe for both sbclient.dll and monitor.netmodule
- A proven manifest has been added and that the expected files were uploaded during testing (through the Visual Studio window - debugging modules)
- The same BadImageFormatException is thrown in BackgroundWorker.OnDoWork (), and the call stack shows the call to dotnetapi.dll ... DefaultDomain.Initalize ().
I checked that msvcm80.dll does not have a manifest, I believe that this is the only downloaded file that does not have a manifest :)
Interesting find
When I load monitor.netmodule in Reflector , it says:
'monitor.netmodule' does not contain an assembly manifest.
Although it displays an error, Reflector is still able to parse the managed code.