这几乎是不可能的。请继续阅读以了解原因。
编译器将赢得这场比赛,每次......
连续两次编译同一个项目,即使不对源代码或项目设置进行任何更改,也总是会产生不同的可执行文件。
造成这种情况的原因之一是 Windows 用于 EXE 文件的 PE(可移植可执行文件)格式包含一个时间戳,该时间戳指示构建 EXE 的日期和时间,每当您构建项目时,VB6 编译器都会更新该时间戳。除了整个 EXE 的“主”时间戳之外,EXE 中的每个资源目录(图标、位图、字符串等存储在 EXE 中的位置)也有一个时间戳,编译器在构建新的时也会更新该时间戳。 EXE文件。除此之外,EXE 文件还有一个校验和字段,编译器会根据 EXE 的原始二进制内容重新计算该字段。由于时间戳更新为当前日期/时间,因此每次重新编译项目时,EXE 的校验和也会发生变化。
但是,但是……我发现了这个非常酷的 EXE 编辑工具,它可以撤销这个编译器的诡计!
有 EXE 编辑工具,例如PE Explorer,声称能够将 EXE 文件中的所有时间戳调整为固定时间。乍一看,您可能认为您可以将两个 EXE 副本中的时间戳设置为相同的日期,并最终得到等效的文件(假设它们是从相同的源代码构建的),但事情比这更复杂:每次编译代码时,编译器都可以自由地以不同的顺序写出资源(字符串、图标、文件版本信息等),并且您无法真正阻止这种情况的发生。资源存储为独立的数据“块”,可以在生成的 EXE 中重新排列,而不会影响程序的运行时行为。
如果这还不够,编译器可能会在未初始化的内存区域中构建 EXE 文件,因此 EXE 的某些部分可能包含编译器运行时内存中的点点滴滴,从而创建更多差异。
至于MD5...
您没有误解 MD5 散列:给定相同的输入, MD5 将始终产生相同的散列。这里的问题是这种情况下的输入(EXE 文件)不断变化。
结论:源代码控制是你的朋友
至于解决您当前的困境,我将留给您:将特定的 EXE 与特定版本的源代码相关联更多的是一个政策问题,必须以某种方式强制执行,而不是其他任何事情。试图在没有任何上下文的情况下弄清楚 EXE 来自哪个版本是不可靠的。您需要借助其他工具进行跟踪。例如,确保每个构建为您的 EXE 生成不同的版本号,并且该版本可以轻松地与您的版本控制系统中的特定修订/分支/标签/任何内容配对。为此,一些开发人员使用源代码控制,而其他开发人员使用“我保留在我的网络文件夹中的 1997 年源代码的副本,因为它是我的代码无论如何,源代码控制都是为娘娘腔的”不会帮助使这变得更容易。我会让每个人都喝源代码控制 Kool-Aid 并遵守立即创建构建的标准政策。
每当我们构建项目时,我们的构建服务器(我们使用Hudson)确保编译的 EXE 版本被更新以包含当前构建号(我们使用版本号插件和自定义构建脚本来执行此操作),以及当我们发布构建,我们在 Subversion 中创建一个标签,使用版本号作为标签名称。构建服务器存档发布构建,因此我们始终可以获得提供给客户的特定 EXE(和安装程序)。对于内部测试,我们可以选择从构建服务器中提取存档的 EXE,或者只是告诉构建服务器从我们在 Subversion 中创建的标签重新构建 EXE。
我们也永远不会从构建服务器以外的任何机器向 QA 或客户发布任何二进制文件。这可以防止“在我的机器上工作”的错误,并确保我们总是从源代码的“已知”副本编译(它只提取和构建我们的 Subversion 存储库中的代码),并且我们总是可以关联给定的具有创建它的代码的确切版本的二进制文件。