You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何验证已加载的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;
}

说明

  1. assembly.Location会返回程序集加载时的磁盘路径(如果是从磁盘加载),读取该文件即可获取已加载副本的字节
  2. 对于内存加载的程序集,通过反射调用内部的GetRawBytes方法提取内存中的程序集原始字节,该方法在.NET Framework中可用
  3. 最后对比两个哈希值即可判断已加载副本与磁盘原始文件是否一致

内容的提问来源于stack exchange,提问作者Niels Bosma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:35:42