[英]DLL identification in the GAC
我试图通过解析此StackOverflow问题中投票最多的答案来理解GAC中的DLL标识: .NET中的GAC是什么?
作者向我们介绍了C:\\ Windows \\ assembly \\ GAC_64 \\ System.Data的树结构,并以结尾。 。 。
在这里您可以看到System.Data的版本2.0.0.0__b77a5c561934e089。
DLL由5个部分标识:
Name Version Architecture Culture Public Key
...这就是我不清楚的部分。 到达树上的叶子后,如何提取DLL标识的那5个部分,并且与程序集名称有任何关系?
在该示例中,我正在使用程序集的是具有以下名称的目录:
v4.0_2.0.6178.1045__d45c8e156fba2841
...在该目录中有一个DLL,其名称类似于
Ab3d.DXEngine.dll
...那么我该如何提取其识别的五个部分?
编辑:
下面的Lifu Huang建议,有一种方法可以从Visual Studio中访问ILDASM。 我没有内置的方法(VS 2013),但是有一种方法可以添加它,如下所述: http : //dailydotnettips.com/2016/01/05/did-you-know-you-can -launch-ildasm-tool-from-inside-visual-studio-itself-how // ...所以我这样做了,当我尝试在GAC中的DLL上运行ILDASM时,我从ILDASM收到一条错误消息,说“ 受保护的模块-不能拆卸 ”
如何提取其标识的五个部分?
您可以在CLR标头和程序集的元数据中找到它们。
实际上,每个托管模块(dll或exe)都包含四个部分:
元数据 (此处是介绍该主题的博客文章 )。 元数据表主要有三种类型:
IL代码 (从源代码生成的IL代码)
如果知道格式,则可以通过编程方式读取元数据。 这是一些执行此操作的代码。 链接
public static CorFlagsReader ReadAssemblyMetadata(Stream stream)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
long length = stream.Length;
if (length < 0x40)
return null;
BinaryReader reader = new BinaryReader(stream);
// Read the pointer to the PE header.
stream.Position = 0x3c;
uint peHeaderPtr = reader.ReadUInt32();
if (peHeaderPtr == 0)
peHeaderPtr = 0x80;
// Ensure there is at least enough room for the following structures:
// 24 byte PE Signature & Header
// 28 byte Standard Fields (24 bytes for PE32+)
// 68 byte NT Fields (88 bytes for PE32+)
// >= 128 byte Data Dictionary Table
if (peHeaderPtr > length - 256)
return null;
// Check the PE signature. Should equal 'PE\0\0'.
stream.Position = peHeaderPtr;
uint peSignature = reader.ReadUInt32();
if (peSignature != 0x00004550)
return null;
// Read PE header fields.
ushort machine = reader.ReadUInt16();
ushort numberOfSections = reader.ReadUInt16();
uint timeStamp = reader.ReadUInt32();
uint symbolTablePtr = reader.ReadUInt32();
uint numberOfSymbols = reader.ReadUInt32();
ushort optionalHeaderSize = reader.ReadUInt16();
ushort characteristics = reader.ReadUInt16();
// Read PE magic number from Standard Fields to determine format.
PEFormat peFormat = (PEFormat)reader.ReadUInt16();
if (peFormat != PEFormat.PE32 && peFormat != PEFormat.PE32Plus)
return null;
// Read the 15th Data Dictionary RVA field which contains the CLI header RVA.
// When this is non-zero then the file contains CLI data otherwise not.
stream.Position = peHeaderPtr + (peFormat == PEFormat.PE32 ? 232 : 248);
uint cliHeaderRva = reader.ReadUInt32();
if (cliHeaderRva == 0)
return new CorFlagsReader(0,0,0, peFormat);
// Read section headers. Each one is 40 bytes.
// 8 byte Name
// 4 byte Virtual Size
// 4 byte Virtual Address
// 4 byte Data Size
// 4 byte Data Pointer
// ... total of 40 bytes
uint sectionTablePtr = peHeaderPtr + 24 + optionalHeaderSize;
Section[] sections = new Section[numberOfSections];
for (int i = 0; i < numberOfSections; i++)
{
stream.Position = sectionTablePtr + i * 40 + 8;
Section section = new Section();
section.VirtualSize = reader.ReadUInt32();
section.VirtualAddress = reader.ReadUInt32();
reader.ReadUInt32();
section.Pointer = reader.ReadUInt32();
sections[i] = section;
}
// Read parts of the CLI header.
uint cliHeaderPtr = ResolveRva(sections, cliHeaderRva);
if (cliHeaderPtr == 0)
return null;
stream.Position = cliHeaderPtr + 4;
ushort majorRuntimeVersion = reader.ReadUInt16();
ushort minorRuntimeVersion = reader.ReadUInt16();
uint metadataRva = reader.ReadUInt32();
uint metadataSize = reader.ReadUInt32();
CorFlags corflags = (CorFlags)reader.ReadUInt32();
// Done.
return new CorFlagsReader(majorRuntimeVersion, minorRuntimeVersion, corflags, peFormat);
}
您需要的许多信息都可以从System.Reflection AssemblyName对象中轻松获得。
该代码将获得System.Web.dll
的强名,处理器体系结构,版本和公共密钥令牌:
var n = System.Reflection.AssemblyName.GetAssemblyName(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.web.dll");
Console.WriteLine(String.Format("{0} {1} {2} {3}", n.Name, n.Version, n.ProcessorArchitecture, BitConverter.ToString(n.GetPublicKeyToken())));
输出:
System.Web 4.0.0.0 Amd64 B0-3F-5F-7F-11-D5-0A-3A
如果您不想为此编写程序,则还可以使用PowerShell脚本执行相同的操作:
[reflection.assemblyname]::GetAssemblyName("${pwd}\System.Web.dll") | fl
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.