ProcessorArchitecture and Assembly.FullName
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:
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.
Related to 1).
People use Assembly.FullName as a key to something, then use assembly
reference to look up. This no longer works.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.