If you haven’t noticed, assemblies in .Net framework 2.0 have a new name attribute ProcessorArchitecture. The attribute is exposed in AssemblyName class as a property ProcessorArchitecture.

 

If you pay a little more attention, you will notice that the output of gacutil.exe is different from what Assembly.FullName says.

 

C:\>gacutil -l system

Microsoft (R) .NET Global Assembly Cache Utility.  Version 2.0.50908.00

Copyright (c) Microsoft Corporation.  All rights reserved.

 

The Global Assembly Cache contains the following assemblies:

  system, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro

cessorArchitecture=MSIL

 

Number of items = 1

 

C:\>fullname C:\Windows\Microsoft.Net\Framework\v2.0.50727\system.dll

Using Assembly.ReflectionOnlyLoadFrom:

FullName: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Location: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\system.dll

Codebase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/system.dll

 

Specifically, Assembly.FullName does not give you the processorArchitecture!!!

 

Now here is the big question: WHY?

 

In fact, we have made the change to include processorArchitecture in Assembly.FullName. When we checked in the change, it caused a massive regression. We fixed all the breaks. But because of the scale of the break it caused, we backed out the change, and took it to DDCC (DDCC stands for Developer Division Compatibility Council. It is a council to review every breaking change in Visual Studio, including .Net framework and CLR). The proposal is rejected by DDCC, fearing it will break many applications. We tried a few other not-so-breaking ways to introduce processorArchitecture to the display name, but none of them is satisfactory. So we have arrived at the current state: Assembly.FullName gives you an assembly’s display name without processorArchitecture.

 

The problems we have seen with the change to include processorArchitecture in Assembly.FullName are:

 

  1. Ref-Def matching. In v1.0/v1.1, essentially there is no difference between assembly reference and assembly definition. People use string comparison to do ref-def matching. This breaks down when processorArchitecture is added to the assembly definition (Assembly.FullName).

    We introduced the API AssemblyName.ReferenceMatchesDefinition, hoping people will move away from using string comparison APIs to compare assembly names.
  2. Related to 1). People use Assembly.FullName as a key to something, then use assembly reference to look up. This no longer works. 
     
  3. Cross platform Remoting/Serialization. Remoting/Serialization emits the assembly’s identity to binary blob so that the type can be constructed when de-serialized. When processorArchitecture is added to Assembly.FullName, you can no longer serialize a type from an x86 assembly to AMD64 platform, since the original processorArchitecture (of “x86”) is carried over to AMD64 platform, the type can’t be instantiated.

    This actually reveals some inefficiency in Remoting/Serialization engine --- You can’t control how types are instantiated when cross platform.

I am sure people will find other problems if we had included processorArchitecture in Assembly.FullName.

 

But this leaves us a huge void --- There is no managed way to get the full display name of an assembly.

 

It is not a pleasant world. But we have to accept that.

 

Now if you really want to get the full display name of an assembly, you have to resort to unmanaged fusion API.

 

Assuming you use my Sample Managed GAC API Wrappers, you can use the following code snippet to achieve that:

 

                                                String GetFullDisplayName(Assembly asm)

                                                {

                                                                AssemblyName asmName = asm.GetName();

                                                                IAssemblyName fusionName = null;

                                                                int hr = 0;

 

                                                                // v1.0\v1.1 assembly, nothing to do here.

                                                                if (asmName.ProcessorArchitecture == ProcessorArchitecture.None)

                                                                {

                                                                                return asm.FullName;

                                                                }

 

                                                                hr = Utils.CreateAssemblyNameObject(

                                                                                out fusionName,

                                                                                asm.FullName,

                                                                                CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,

                                                                                IntPtr.Zero);

 

 

                                                                if (hr >= 0)

                                                                {

                                                                                IntPtr pa = Marshal.AllocCoTaskMem(4);

                                                                                Marshal.WriteInt32(pa, (int)asmName.ProcessorArchitecture));

                                                                                hr = fusionName.SetProperty(ASM_NAME_ARCHITECTURE, pa, 4);

                                                                                Marshal.FreeCoTaskMem(pa);

                                                                }

 

                                                                if (hr >=0 )

                                                                {

                                                                                StringBuilder sDisplayName = new StringBuilder(1024);

                                                                                int iLen = 1024;

          

                                                                                hr = fusionAsmName.GetDisplayName(sDisplayName, ref iLen, (int)AssemblyNameDisplayFlags.ALL);

 

                                                                                if (hr >= 0 )

                                                                                {

                                                                                                return sDisplayName.ToString();

                                                                                }

                                                                }

 

                                                                if (hr < 0)

                                                                {

                                                                                Marshal.ThrowExceptionForHR(hr);

                                                                }

 

                                                }

                                }

 

 ASM_NAME_ARCHITECTURE is defined in fusion.h, which is part of .Net framework 2.0 SDK.