如何验证已加载的X.dll与磁盘上的原文件是否一致?
问题解决:验证已加载程序集与磁盘原始文件的哈希差异
错误原因
你用GetManifestResourceStream("X.dll")返回null是必然的——这个方法的作用是读取嵌入到当前调用程序集中的资源文件,而不是获取已加载的X.dll程序集本身的字节流。X.dll是独立的加载程序集,不是嵌入资源,所以该方法完全不适用。
解决方案
要计算已加载程序集的哈希,需要分两种情况处理:
- 如果程序集是从磁盘加载的(包括影子复制的副本),直接读取其加载路径对应的文件字节
- 如果程序集是从内存加载的(如通过
Assembly.Load(byte[])加载),则从内存中提取程序集的原始字节
修改后的完整代码
static void Check() { Assembly assembly = Assembly.GetAssembly(typeof(X.Y)); byte[] loadedDllHash = GetAssemblyHash(assembly); byte[] fileOnDiskHash = GetFileHash(@"C:\foo\X.dll"); bool isIdentical = CompareByteArrays(loadedDllHash, fileOnDiskHash); Console.WriteLine($"已加载的X.dll与磁盘原始文件是否一致:{isIdentical}"); } static byte[] GetAssemblyHash(Assembly assembly) { // 优先处理从磁盘加载的程序集 if (!string.IsNullOrEmpty(assembly.Location)) { using (FileStream stream = File.OpenRead(assembly.Location)) { return CalculateHash(stream); } } // 处理从内存加载的程序集(调用内部方法提取字节) var manifestModule = assembly.ManifestModule; var getRawBytesMethod = manifestModule.GetType().GetMethod( "GetRawBytes", BindingFlags.Instance | BindingFlags.NonPublic ); if (getRawBytesMethod != null) { byte[] rawAssemblyBytes = (byte[])getRawBytesMethod.Invoke(manifestModule, null); using (MemoryStream stream = new MemoryStream(rawAssemblyBytes)) { return CalculateHash(stream); } } throw new InvalidOperationException("无法获取程序集的字节流以计算哈希"); } static byte[] GetFileHash(string filePath) { using (FileStream stream = File.OpenRead(filePath)) { return CalculateHash(stream); } } static byte[] CalculateHash(Stream stream) { using (SHA256 sha256 = SHA256.Create()) { return sha256.ComputeHash(stream); } } static bool CompareByteArrays(byte[] a, byte[] b) { if (a.Length != b.Length) { return false; } for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) { return false; } } return true; }
说明
assembly.Location会返回程序集加载时的磁盘路径(如果是从磁盘加载),读取该文件即可获取已加载副本的字节- 对于内存加载的程序集,通过反射调用内部的
GetRawBytes方法提取内存中的程序集原始字节,该方法在.NET Framework中可用 - 最后对比两个哈希值即可判断已加载副本与磁盘原始文件是否一致
内容的提问来源于stack exchange,提问作者Niels Bosma
相关产品推荐
相关产品推荐

