这两个从同一源代码生成的DLL文件有什么区别?

10

我所有的代码都在源代码控制下,所以我可以100%确定源代码没有改变。但是如果我构建一个C# DLL两次,它们的内容会略有不同。我可以通过仅构建,然后再次构建来100%重现此问题。

这似乎对程序没有影响,但是像用于从两个MSI文件创建补丁的MSIMSP之类的工具会受到这些微小更改的影响。这使得(我的产品)的补丁比应该大40倍。

我已经反编译了两个DLL和它们的程序集信息、类等...都完全相同。文件大小也完全相同,但当然有不同的创建时间。所以我真的无法理解发生了什么变化。

所以我深入挖掘了一下。

我使用WinDiff查找更改,然后在十六进制编辑器中进行交叉引用。WinDiff显示第二行和约80%的行中有变化。

在十六进制编辑器中,我看到第一个更改的字节是字节0x088(字节136)。这似乎是这个“行”上唯一更改的字节。我很难找到第二个更改,因为WinDiff没有告诉我更改的确切字节偏移量。

下面是变化的图像,右侧文件是新文件的内容。 Hex view

熟悉(C#)DLL文件结构的人知道更改的字节可能意味着什么吗?或者更好的办法是如何确保在重新构建它们时DLL文件保持完全相同?


有时候我的bin/release文件夹中会出现一个名为$RANDOM_SEED$的文件,而且每次我重新构建时该文件的内容都会发生变化。我没有深入研究过,但我可以想象这是两个变化之一。需要有人进行一些研究。编辑:(它可能是nunit,对dll没有影响,所以忘记我的评论)https://dev59.com/XVkS5IYBdhLWcg3wHDHU#40382757 - Mafii
也许值得尝试一下像Vedit这样的好用的文本/十六进制编辑器。我从1989年开始使用它。即使在现在有IDE和智能感知的时代,它仍然是一个非常实用的工具。www.vedit.com - Michael Gorsich
3
似乎如何判断两个Net DLL是否相同从不同角度探讨了相同的问题。 - Damien_The_Unbeliever
1
https://dev59.com/GGox5IYBdhLWcg3w3X9S - Matteo Umili
@Matteo的链接应该能解决这个问题! - TaW
这是IMAGE_FILE_HEADER.TimeDateStamp - Hans Passant
2个回答

5
这可能与“Build”和“Rebuild”之间的差异有关。 Visual Studio中Build Solution、Rebuild Solution和Clean Solution之间的区别是什么? 如果它认为不需要重新构建项目,它就不会重新构建。如果项目的部分构建位没有更改,它也可能使用。
执行构建使用幕后元数据,因此您的dll可能会有所不同。 为什么在没有代码更改的情况下进行清理构建会产生不同的dll? 解决方案: 您需要执行确定性构建,如此处所述。

但是多次构建应该每次都会生成完全相同的二进制文件,对吧? - Mafii
1
@Mafii 不幸的是,总是有一些事情在幕后发生... 元数据看起来像是 https://dev59.com/xHVD5IYBdhLWcg3wDHDm 所以不,它们不会产生相同的二进制文件。 - Fuzzybear
@Fuzzybear 有没有办法忽略那些元数据字节来创建补丁?(也许我应该把这个问题单独问一下) - Roy T.
@Roy T 据我所知暂无此功能,抱歉。我会尝试重新构建而不是编译,如果这样不行,那么我会问如何剥离元数据等...也许还有其他编译器可以满足您的需求? - Fuzzybear
1
@FuzzyBear 我偶然发现了http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html,其中提到Roslyn有一个/deterministic构建参数。希望这个方法有效:D - Roy T.
惊人的发现@RoyT。和他的第一句话:“庆祝本应从一开始就存在的功能似乎很愚蠢”,我将在我的答案中添加链接。 - Fuzzybear

0

如果您对dll进行了更改,那么其大小将受到影响。我给枚举类型添加了一些额外的属性,文件大小增加了约3KB。

也可能是由于解压缩而导致文件看起来不同却未被察觉的更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接