I received a question from a customer a few days ago about assembly versioning. I receive questions quite often, of which >90% surprisingly enough come via Brad. I can only imagine what his inbox looks like every morning! Anyway, the question touched on the focus for this post which is the relationship between the Everett and Whidbey GACs. Before I go any further, I’m happy to report that the relationship is sensible and easy to understand. Too often, things don’t make a lot of sense and that always bugs me.
The customer’s question was actually about assembly versioning in the case that you want to support Everett and Whidbey, which I hope to cover tomorrow, since that’s when I told them I’d give them an answer ;)
First things first, on the surface it seems like interop between the GACs is what is wanted. In actual fact, it is the behaviour of the CLR loader and gacutil.exe that is really the interesting part. The GACs themselves are passive and don’t do anything other than act as a quite compelling directory structure for holding code w/o any naming conflicts.
Migrating the Everett GAC to the Whidbey GAC
We don’t do anything like this. This would have been the wrong direction for multiple reasons. Just thought I’d take care of this one up-front.
Hard linking assemblies between the Everett and Whidbey GACs as a Perfomance Enhancement
I’m glad that we didn’t do anything like this either. Ouch. OK, now onto the real answers.
Whidbey CLR Loader GAC Probing
The Whidbey CLR loader – Fusion in this case – probes for assemblies in the Everett and Whidbey GACs when an assembly request comes through the system. I’ll skip the exact algorithm and any optimizations that we might do. The high-order bit here is that we do indeed look in both GACs, so there is no need to stop using the Everett GAC for Everett assemblies since we look there. In fact, as you’ll find out below, you cannot stop using the Everett GAC.
Gacutil.exe, the Fusion APIs and installation via MSI (installers)
There are several ways that you can get assemblies installed into the GAC, with the last one being the recommended option. The big thing I wanted to know when I asked the question is what the expected behaviour was when I added an assembly to the GAC via these different methods.
Question:
Do the Whidbey tools put Everett assemblies into the Everett GAC?
Given:
Everett and Whidbey .NET Frameworks are installed on the machine
Assemblies:
1) 1 assembly compiled against Everett csc.exe (csharp compiler)
2) 1 assembly compiled against Whidbey vbc.exe (vb compiler)
Note: the compilers (vb, csharp) don’t matter for the assemblies above. I’m just trying to mix it up a little. It is the .Net Framework versions that matter.
Tools:
A) Everett Gacutil
B) Everett Fusion APIs
C) Whidbey Gacutil
D) Whidbey Fusion APIs
E) MSI installation
Scenarios + expected outcome:
1. (1) + (A) -- Everett GAC
2. (1) + (B) -- Everett GAC
3. (1) + (C) -- Everett GAC
4. (1) + (D) -- Everett GAC
5. (1) + (E) -- Everett GAC
6. (2) + (A) -- failure
7. (2) + (B) -- failure
8. (2) + (C) -- Whidbey GAC
9. (2) + (D) -- Whidbey GAC
10. (2) + (E) -- Whidbey GAC
Scenarions 6 and 7 fail since Whidbey-compiled assemblies are not loadable via the Everett CLR. Also, since processor architecture is a major part of Whidbey, it would be difficult to store Whidbey assemblies in the Everett GAC in a reasonable manner.
Why does Whidbey put Everett assemblies into the Everett GAC?
We continue putting Everett assemblies into the Everett GAC for two reasons:
- Everett apps still require those assemblies and will only be able to use them if they are in the Everett GAC since the Everett CLR loader knows nothing about the Whidbey GAC. It is much easier and smarter for the Whidbey loader to look in the Everett GAC.
- Everett assemblies didn’t have the concept of processor architecture, which the Whidbey GAC is heavily based on, so it doesn’t make sense to store Everett assemblies in that new structure.
- Everett is going to live for a long time. Let’s not mess with a good thing ;)
That was actually 3 reasons, if you count the last one.
Is there an Everett GAC if there is no Everett .NET Framework on the Machine, but only Whidbey?
Yes. The Everett GAC is created as needed when Everett is not on machine. This means that the Everett GAC structure is auto-created when the first Everett-era assembly is added to the Whidbey-only machine. If Everett was also on this machine, the Everett GAC would have been created at the point that the Everett .NET Framework was installed.