10

This question relates to these previous question on SO

Any CPU question 1 and Any CPU Question 2

I have a application which was originally built on Win XP using Visual Studio 2005 (don't laugh!). This app calls into our win32 C++ dll. The C# components which call the C++ dlls were built with the "Any CPU" configuration and have been happily working on Win XP without any issue.

We are now moving to Win 7 and the release version of our app (which was built on Win XP with VC 2005) works fine. However with the roll out of win 7 to our users we have now taken the opputunity to move to VS 2010 and I have built the C# components on win 7 with VC 2010 but now when running this version I get lots "unable to load abc.dll" where abc.dll is our win32 c++ components.

I understand that recompiling the C# assemblies with x86 config will solve the problem but what I don't understand is how the release version c# assemblies built with Win-XP/Visual studio 2005 (Any CPU config) are able to run on Win 7 without any issues? Surely these C# assemblies built with "Any CPU" should JIT to 64 bit code when loaded in Win 7 and cause BadImageFormatException or other errors because they call Win32 C++ dlls.


UPDATE : I have Some more information that have been requested in the comments below.

  1. On my Windows 7 box I right click on my computer and look at the properties. The System information says "System Type : 64 bit operating system" confirming this is a Win64 OS.

  2. Opening up the solution in VC2005 on Windows XP When viewing the configuration manager for the solution I can confirm ALL the C# projects are platform type "Any CPU".

  3. When running the release build (which was done on VC2005/win xp) on 64bit Win 7 machine, I task manager shows the image name as "Test.exe *32", this confirms it is jit'd and loaded into 32bit process.

Community
  • 1
  • 1
Ted
  • 345
  • 5
  • 18
  • 1
    Is the *target environment* bitness the same in both cases? It could be another sneaky change going on? –  Sep 06 '11 at 18:43
  • There's something else happening here that you haven't told us. An AnyCPU assembly will be a 64 bit process on a 64 bit system. It doesn't matter where it was built. – David Heffernan Sep 06 '11 at 19:01
  • 3
    Only the Platform target setting on the EXE project matters, that determines the bitness of the process. Beware that the active platform selection in Build + Configuration Manager does *not* apply to managed projects. – Hans Passant Sep 06 '11 at 19:03
  • Oh oh! When executing the build from the XP/VS2005 combination, check the bitness using task manager in Windows 7. If your exe is loaded with *32 it's 32-bit, if it's not, it's 64-bit. Let us know if the XP/VS2005 build executes as 32 or 64 bit. – Joshua Sep 06 '11 at 19:08
  • Are you sure your windows 7 system where the original release worked was a 64bit system? Not all Windows 7 installations are 64bit, after all. – Joel Coehoorn Sep 06 '11 at 22:02
  • see above for more information – Ted Sep 07 '11 at 13:32

3 Answers3

4

Under Win7, the process is 64-bit. 64-bit processes cannot have 32-bit DLLs in them, that's a pretty fundamental design limitation of Windows.

And the fact that this managed code EXE calls into a 32-bit DLL is not obvious from the get-go - P/Invoke, as well as COM interop, works via late binding. So the EXE is loaded, the loader does not check the dependencies - for one thing, the dependencies might be conditional - then the DLL loading time comes, wackiness ensues.

So yeah, if you have managed code with known 32-bit dependencies, you better specify a 32-bit CPU at compile time. Or recompile the C++ parts to 64 bits, that's also an option.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • 4
    So why he **didn't** have to specify 32-bit with VS2005? – Branko Dimitrijevic Sep 06 '11 at 18:29
  • 3
    Thanks Seva but you missed the point, Branko understands it : The question is why does it work when bult on Win XP/VC2005 with "Any CPU" but it does not work when built with Win 7/VC2010 "Any CPU" – Ted Sep 06 '11 at 18:35
  • Maybe the build machine bitness affects the EXE image... Not sure :) It's not obvious from the question what would be the result of a VS2005 build on a Win7 box. – Seva Alekseyev Sep 06 '11 at 18:36
  • @Seva "Maybe the build machine bitness affects the EXE image". No. "It's not obvious from the question what would be the result of a VS2005 build on a Win7 box." Yes it is. An AnyCPU target runs x64 on an x64 system, x86 on an x86 system. – David Heffernan Sep 06 '11 at 19:02
  • 2
    Don't you mean: "That's a pretty fundamental limitation of any operating system". – Jonathan Dickinson Sep 06 '11 at 19:03
2

I can confirm that you should get BadImageFormatException. Is it possible that the compilation on XP was monkeyed with badly enough that it's not actually building AnyCPU but rather builds x86 labelled as AnyCPU. I can also confirm it's possible to monkey with a project file badly enough that it would do that and the project upgrade component chokes on that.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • monkeyed ...is tht a new technical term :-). By monkeyed I take it you mean compiled to IL code? – Ted Sep 07 '11 at 14:04
1

One possible explanation is that one of your projects in the solution on the 32-bit development system had a binary reference to a 32-bit assembly, which would force it to be loaded as a 32-bit process even on 64-bit systems.

  • If the entry point to my process is in a C# exe then surely it would have to be JIT'd into a 32bit/64bit exe and loaded into the appropriate process first and the susbsequent calls to win 32 (which are late bound anyway)should generate an exception (bad image Format) .....or have i missed out something here? – Ted Sep 07 '11 at 14:03
  • It is my experience that while native DLLs are indeed late-bound and will generate the exception you mention if there's a bitness mismatch, non-project references to managed DLLs that are compiled as 32-bit do force the process to start as a 32-bit application. – 500 - Internal Server Error Sep 07 '11 at 16:19