S h o r t S t o r i e s

// Tales from software development

Dynamic load of 32 bit class library from 32 bit Windows Service fails with BadImageFormatException

leave a comment »

We have an HL7 interface that runs as a Windows Service that is deployed at half a dozen customer sites. Each site has slightly differing interfacing requirements and this is handled using a site specific assembly that is dynamically loaded by the service.

Until recently we haven’t had to worry about whether the service was running as a 32 bit or 64 bit process but some of the more recent deployments have used a site specific plugin assembly that has dependencies on other 32 bit assemblies. So, the target of the automated build was changed from ‘Any CPU’ to ‘x86’. Note that no change was made to the solution or project files.

A few weeks later I deployed a new version of a plugin assembly to a test environment at one of our customer sites and found that the service would not start due to a BadImageFormat Exception being thrown when the service tried to dynamically load the plugin assembly. The intention was that all class library assemblies would be compiled as ‘AnyCPU’ but in fact this plugin assembly had been targeted to ‘x86’ and so was 32 bit only. This should not have been a problem however as the Windows Service executable was also compiled as 32 bit only.

I used DumpBin.exe to confirm that the headers in the two assemblies indicated that these were 32 bit only. [Edit: See this post that explains why this doesn’t work.]

Then I enabled fusion logging to see why the load was failing and at first glance the log didn’t appear to shed any light on why the load failure was happening:

*** Assembly Binder Log Entry  (10/07/2013 @ 11:52:12) ***

The operation failed.
Bind result: hr = 0x8007000b. An attempt was made to load a program with an incorrect format.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
Running under executable  C:\Program Files (x86)\Vitality\HL7Interface\InterfaceService\Vitality.HL7.Processing.Service.exe
--- A detailed error log follows.

=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: Where-ref bind. Location = C:\Program Files (x86)\Vitality\HL7Interface\InterfaceService\Vitality.HL7.Processing.RFH.dll
LOG: Appbase = file:///C:/Program Files (x86)/Vitality/HL7Interface/InterfaceService/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL Calling assembly : (Unknown).
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\Program Files (x86)\Vitality\HL7Interface\InterfaceService\Vitality.HL7.Processing.Service.exe.Config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Vitality/HL7Interface/InterfaceService/Vitality.HL7.Processing.RFH.dll.
LOG: Assembly download was successful. Attempting setup of file: C:\Program Files (x86)\Vitality\HL7Interface\InterfaceService\Vitality.HL7.Processing.RFH.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Vitality.HL7.Processing.RFH, Version=2.0.0.0, Culture=neutral, PublicKeyToken=f529d7a12981f1ee
ERR: Failed to complete setup of assembly (hr = 0x8007000b). Probing terminated.

It took me a few minutes to spot that line 6 indicates that the 64 bit loader is being used:

Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll

Similarly, line 23 indicates that the machine configuration file being used is from the Framework64 folder.

This doesn’t make any sense as the service executable is running as a 32 bit process.

It seems that setting the PlatformTarget property to “x86” when invoking MSBuild in the automated build to build the project files is not having the effect I thought it did.

The project files in Visual Studio are set to PlatformTarget = “AnyCPU” and have references to 64 bit Framework assemblies. When the project files are compiled in the automated build with PlatformTarget=”x86″ the 32 bit flag is set on the assemblies created but the 64 bit framework assembly references remain unchanged.

The solution was to configure the platform targets for each project in Visual Studio as required (“x86” for executables and “AnyCPU” for class libraries) and then update the automated build to build the solution files rather than the project files.

Advertisements

Written by Sea Monkey

July 12, 2013 at 8:00 pm

Posted in Debugging, Development

Tagged with , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: