System.Badimageformatexception when migrating windows service from 32 to 64 bit OS

Recently we migrated application built against .NET Framework v4.0.30319 from 32 bit Windows server 2003 to 64 bit Windows server 2008.

Application (Windows service), lets call it Service.exe, also happens to reference some dependent assemblies (dlls). All assemblies except one assembly were built for AnyCPU (x86 and x64) like in an example below:

  • Service.exe (AnyCPU)
  • ReferencedFile1.dll (AnyCPU)
  • ReferencedFile2.dll (x86)

When we installed Service.exe as a windows service with 32 bit installutil.exe service installed successfuly.

Installing assembly 'c:\Program Files (x86)\EVizija\Service.exe'. Affected parameters are:
logtoconsole = logfile = c:\Program Files (x86)\EVizija\Service.InstallLog assemblypath = c:\Program Files (x86)\EVizija\Service.exe Installing service Service...
Service Service has been successfully installed.

After successful install, starting windows service throws an exception.

Application: Service.exe Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.BadImageFormatException
Stack:
at Service.Service..ctor() at Service.Program.Main(System.String[])

How can this be if the install was succesful? Some blog posts hinted us towards:

It seems that you are using the 64-bit version of the tool to install a 32-bit application. Look for the 32-bit version of the tool here:

C:\Windows\Microsoft.NET\Framework\v4.0.30319

and it should install your 32-bit application just fine.

As said before, we didn't have problems installing the service but starting it. After some investigation with corflags.exe we figured out that it might be that running assembly Service.exe started in 64 bit mode and when trying to load 32 bit referenced assembly in 64 bit process throws exception.

The solution is to change corflags section of a PE file Service.exe to 32 bit.

Corflags section of a Service.exe file before

Corflags section of a file after seting 32BITREQ flag (32 bit)

Interpreting corflags