Platform Agnostic apps failing on a 64 bit machine.
Ran into this issue yesterday, thought I will post it out here for anyone who runs into the same issue, since this is a very common issue with open source projects.
After wiring up the bits from CruiseControl.Net 1.4.4 SP1 with TFS on a machine running 64 bit OS, I was getting strange exceptions like
“Could not load file or assembly ‘Microsoft.TeamFoundation.VersionControl.Client, Version=188.8.131.52, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies…..”
The DLL in question seemed to be present in the GAC. So what really went wrong?
Windows Loader is responsible for deciding how to load and execute a program and the way it does that is by looking at the PE header on the app. This PE Header bit is set when the Platform Target in the build configuration of Visual Studio is set to one of the following:
- x64: 64-bit—denotes that the developer has built the assembly specifically targeting a 64-bit process.
- x86: 32-bit—denotes that the developer has built the assembly specifically targeting a 32-bit process.
- Any CPU: Agnostic—denotes that the developer built the assembly that can run in either 64-bit or 32-bit mode.
When .Net apps are compiled with the default “Any CPU” your program will run as a 32 bit process on a 32 bit machine or as a 64 bit process on a 64 bit machine. The Windows Loader sees such DLLs as Agnostic DLL’s.
Simply marking the Platform Target as “Any CPU” does not guarantee that it will run on both 32-bit and 64-bit Windows.
Reason: It is not possible to inject a 32-bit DLL into a 64-bit process, so be careful if your program has dependencies on native 32 bit DLLs or is making native calls assuming 32-bit. Exactly what was happening in my case.
Now how can you troubleshoot this issue when you don’t have the source code for an assembly? I use Dumpbin to evaluate this, open up your VS2005/2008 command prompt and run the following command
dumpbin Program.exe /headers
How can you fix such apps to working correctly on a 64 bit machine? Applications and assemblies marked/compiled as a 32 bit can run on 64-bit Windows with WOW64 emulator, so the PE header can be modified to be run as 32 bit
Run the CoreFlags Conversion utility from the VS2005/2008 command prompt
CorFlags.exe Program.exe /32BIT+
This should flip the PE header bit to mark the app/assembly as a 32 bit, this does not affect the build of the assembly in anyway since this just conveys how the JIT compiler should interpret the assembly.
You can turn the bit back on with a
CorFlags.exe Program.exe /32BIT-
So in my case to fix the CruiseControl issue, I just ran the following:
CorFlags.exe CCService.exe /32BIT+
CorFlags.exe CCNet.exe /32BIT+