Have you ever seen BadImageFormatException
or “An attempt was made to load a program with an incorrect format” message?
If so, maybe the program that you tried to run hasn’t been compiled with /platform:x86 option. You are probably wondering why, while writing in C# you should think about what kind of machine (x86 or x64) your program will execute on. Well… in most cases you don’t have to care about it. If your application doesn’t contain any unsafe code and doesn’t import any native modules that are destined for specific CPU architecture, then you can forget about 32/64 bit dilemma. After all C# code gets compiled into intermediate language (CIL) and upon execution framework’s just-in-time compiler will emit native instructions suitable for current platform. Great, but there’s a catch…
Imagine a situation when you import 32 bit DLL in your application. If you run that software on 32 bit operating system everything works as expected. Unfortunately on x64 machine you can get BadImageFormatException while trying to load DLL. Why? Your assembly may be compiled with /platform:anycpu setting. It means that on 32 bit systems your code will be executed with 32 bit CLR version. On 64 bit systems a 64 bit process will be used – and it will cause problems with loading 32 bit DLL. If you provide /platform:x86 setting, then 32 bit version of the CLR will be choosen even on the x64 versions of Windows (utilizing WoW64: Windows 32-bit on Windows 64-bit).
In Visual Studio 2010 you can set targeted platform in project “Properties” window (on “Build” tab). To get there, right click on project file in Solution Explorer and choose “Properties” or use main menu “Project | <you project name> Properties…”.
Microsoft has created useful tool called CorFlags which can be used to show or set the targeted platform of an managed assembly. You can access this program by using Visual Studio Command Prompt or find it directly on your disk (I have it under C:\Program Files\Microsoft.NET\SDK\v2.0\Bin\CorFlags.exe).
Here are some examples of what you may see after checking an EXE file created with various /platform option values (use CorFlags file.name command to check a file):
anycpu |
x86 |
x64 |
Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 1
ILONLY : 1
32BIT : 0
Signed : 0
|
Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 3
ILONLY : 1
32BIT : 1
Signed : 0
|
Version : v4.0.30319
CLR Header: 2.5
PE : PE32+
CorFlags : 1
ILONLY : 1
32BIT : 0
Signed : 0
|
For the scope of this post 2 rows of the CorFlags output are important: PE and 32BIT.
- PE: PE32 means that file can be executed on both x86 and x64
- PE: PE32+ means that it can only be run on 64 bit version of OS
- 32BIT: 1 means that program must be executed on x86 environment.
Understanding 32BIT: 1 meaning is really important if you want to avoid problems with importing 32 bit DLL on 64 bit systems. If 32BIT flag is set and you run PE32 file on x64, then your app will be executed in 32 bit process (under WoW), hence will have a chance to properly import 32 bit DLL. Without this setting 64 bit environment will be chosen which will cause problems.
The good news is that you can easily modify 32BIT flag with CorFlags tool, to do this execute that command:
CorFlags file.exe /32BIT+
And to remove it, try this
CorFlags file.exe /32BIT-
So even if you cannot recompile problematic assembly with proper /platform option you still have a chance of using legacy 32 bit DLLs on 64 bit Windows " />