VSoft Technologies Blogs

rss

VSoft Technologies Blogs - posts about our products and software development.

(This is a technical post about some of the "gotchas" when coding for .NET on 64- and 32-bit architectures.)

The short story:

The TeamFoundation client assemblies are x86-only assemblies. They don't work when called from an x64 .NET Application.

Even though they're in the GAC, you'll get a FileNotFoundException if the CLR tries to load them.

 

My story:

I already knew this, but it took me most of the day to realise that was my problem.

 

The long story:

Microsoft's .NET CLR 2.0 supports three different processor architectures: x86, x64 and IA-64.  This means that there are three different CLR environments. x64 machines can host the x86 CLR alongside the native 64-bit CLR.

 

Although the CLR executes architecture-agnostic Common Intermediate Language (aka MSIL) code, any assembly can be marked as only suitable for one of the particular architectures.This is what happens when you choose a "Platform" type for a Visual Studio project. Choosing 'Any CPU' means that the project Assemblies are marked as language-agnostic CIL code.

 

It all plays out like this:

 

CLR Type Can Be Hosted From Can Load These Assembly Types
x86 x86 or x64 Operating Systems x86, "Any CPU"
x64 x64 Operating Systems x64, "Any CPU"
IA-64 Itanium Operating Systems IA-64, "Any CPU"

 

Or, alternatively:

 

Assembly Type Can Run On
"Any CPU" / MSIL Any CLR
"x86" x86 CLR Only
"x64" x64 CLR Only
"IA-64" IA-64 CLR Only

To find out if an assembly is x86-only, you can use the CorFlags.exe utility which ships with the .NET SDK. You can also use this tool to tweak the assembly type, although doing this will break strong named assemblies and generally cause chaos.

 

When loading a.NET-based process, the .NET Framework decides which version of the CLR to load based on the assembly type. Processes based on "Any CPU" assemblies will load in the native CLR for the host system.

This can lead to some funny situations. For example, the ASP.NET Development Server application is 32-bit only, so any web sites you run on it will run in the x86 CLR. On the other hand, on x64 IIS can run either 32- or 64-bit ASP.NET applications. This means you can move your ASP.NET application from the Development Server to IIS on the same machine, and all of a sudden you will get a BadImageFormatException when an assembly refuses to load any more.

The Twist:

Sometimes you get a FileNotFoundException instead. This is when you try to reference an Assembly which is in the GAC.

 

... and you think "That's odd, I thought that assembly was in the GAC." and you look in the GAC browser, and there it is:

 

 

GAC Viewer In Explorer

 

... the key is the "Processor Architecture" column on the righthand side.

 

As of .NET Framework 2.0, the CLR actually has four different GACs - one for each architecture, and one for "Any CPU" MSIL Assemblies. You can see this quite literally if you disable the GAC Shell extension, and browse to the GAC directory.

 

Each version of the CLR can only load assemblies which exist in its own GAC, or in the architecture-agnostic MSIL GAC. If you try to load an assembly from a different GAC, you'll see the FileNotFoundException.

Showing 2 Comments

Avatar
MT 11 years ago

I have a client that has the .NET 2.0 Framework for BOTH the x86 and x64 (though the GAC shows the Processor Architecture as AMD64). There is an ASP.NET application running via IIS on his web server, but he keeps getting an error and the event log says that is could not file the assembly System.Web or one of its assemblies. When I look at the user's GAC, I see vr. 2.0.0.0 for the System.Web listed twice (once for the x86 and once for the AMD64 Processor Architecture). Is this error being caused because the CLR looks in the GAC for System.Web, but finds 2 versions of this and doesn't know which one to use? Just curious if you could give me some advice/insight on this. Thanks!


Avatar
angus 12 years ago

In some cases it seems like you'll also see "Strong Name Validation Failed" for the same problem, if the assemblies can be found but are built for a different CLR version.



Comments are closed.