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

// Tales from software development

Archive for July 2013

Checking if a .NET assembly is compiled for 32 bit or 64 bit execution

leave a comment »

The traditional way of checking whether a program or dll is compiled as 32 bit or 64 bit is to use the Microsoft DumpBin utility with the /HEADERS switch. However, this doesn’t work for .NET assemblies as the first part of the file is a bootstrap for the .NET runtime and DumpBin will always indicate that the file is 32 bit regardless of whether the .NET code is 32 bit or 64 bit.

The solution is to use the CorFlags utility that ships as part of the Microsoft Platform SDK and the .NET Framework SDK. The output includes a 32BIT value that is set to either 0 to indicate the program is not specifically compiled as 32 bit only (i.e. it’s 64 bit capable) or 1 to indicate it is 32 bit only. For example, this is the output for an assembly compiled using a Platform Target of AnyCPU:

Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1

And this is the output for an assembly compiled with a Platform Target of x86:

Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1

Advertisements

Written by Sea Monkey

July 15, 2013 at 8:00 pm

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.

Written by Sea Monkey

July 12, 2013 at 8:00 pm

Posted in Debugging, Development

Tagged with , ,