如何检查程序集是不是已更改

Posted

技术标签:

【中文标题】如何检查程序集是不是已更改【英文标题】:How to check if an assembly has changed如何检查程序集是否已更改 【发布时间】:2010-11-06 23:15:15 【问题描述】:

是否可以判断程序集是否已更改?

我有一个标准项目,它生成一个名为 MyAssembly.dll 的程序集。

在一个单独的项目中,我读取了程序集并生成了一个哈希。

当我为程序集生成哈希时,每次重新编译时它都是不同的。我已将程序集版本设置为静态,还有其他需要更改的属性吗?

class Program

    static void Main(string[] args)
    
        var array = File.ReadAllBytes(@"MyAssembly.dll");
        SHA256Managed algo = new SHA256Managed();
        var hash = algo.ComputeHash(array);

        Console.WriteLine(Convert.ToBase64String(hash));
    

谢谢

罗汉

【问题讨论】:

你会在那个程序集中有多少个班级? 任意数量的班级,目前只有一个班级 【参考方案1】:

您可能需要使用版本号属性。哈希不起作用,因为任何时候重新编译程序集,它都会有所不同——即使代码根本没有改变。原因是每次编译时,编译器都会在程序集中嵌入一个 guid,并将相同的 guid 放入相应的 .pdb 文件中。每次编译程序集时,guid 都会更改。

这就是调试器将程序集与其 .pdb 文件的正确版本匹配的方式(这也是为什么您必须始终将 .pdb 保存在您发布的任何内容上,并且您不能依赖能够生成匹配的 pdb一个现有的程序集)

【讨论】:

【参考方案2】:

每个程序集都有一个ModuleVersionId GUID,其作用类似于哈希。如果您更改单个字符,模块 id 会更改,但如果您还原它,则会恢复旧的 id。这对于比较程序集的两个版本很有用。

var assembly = Assembly.GetEntryAssembly();
var hashId = assembly.ManifestModule.ModuleVersionId;
Console.WriteLine(hashId);
40744db8-a8fe-4591-9b2c-d9e3e04a2f0a

https://docs.microsoft.com/en-us/dotnet/api/system.reflection.module.moduleversionid?view=net-5.0

【讨论】:

【参考方案3】:

您可以在生成哈希后将其存储在文本文件中,然后在下次重新编译时对其进行检查。

【讨论】:

这就是我正在做的事情,即使代码没有更改,重新编译也会生成新的哈希。【参考方案4】:

好吧,如果它是您自己管理的程序集,我建议您在每次构建该程序集时添加一个版本号和auto-increase 版本号。

然后你可以检查版本号。

【讨论】:

版本号是检查程序集是否已更改、是否兼容的正确方法 是的,但可能是 dll 来自不维护其版本号的外部源(可耻!)。 每次构建时增加版本不会告诉我代码是否已更改。我真正想做的是在重新编译后检查程序集是否已更改。我不想进行选择性构建或创建自定义构建脚本来仅构建已更改的项目。【参考方案5】:

This project 似乎通过反汇编每个文件并在生成MD5 哈希之前删除MVID GUID 以及其他一些位来解决问题。它依赖于ildasm.exe。

【讨论】:

【参考方案6】:

目前它确实不是微不足道的 - 但是 - 我已经为 .net 平台本身,也适用于 ilSpy - 据我所知,这些是未来可以实现特定功能的最佳候选者。

如果您想了解目前如何实施的替代方案,请参阅票证说明。

现在在这里提供两个链接:

.net平台-https://github.com/dotnet/core/issues/5577

ilSpy - https://github.com/icsharpcode/ILSpy/issues/2220

【讨论】:

以上是关于如何检查程序集是不是已更改的主要内容,如果未能解决你的问题,请参考以下文章

如何检查某个程序集是不是存在?

如何检查 pdb 文件是不是对调试程序集有效

检查用户是不是更改了连续子表单记录集的最简单方法?

C#如何在签入策略期间获取挂起更改的程序集

使用 tfs 在 CI 中检查程序集信息

C#如何在签入策略期间获取挂起更改的程序集