代码之家  ›  专栏  ›  技术社区  ›  Tim Visher

如何验证vb6可执行文件的两个副本来自同一个代码库?

  •  4
  • Tim Visher  · 技术社区  · 14 年前

    我有一个版本控制下的程序,已经通过了多个版本。今天出现了这样一种情况:有人设法指向程序的一个旧副本,因此遇到了后来被修复的bug。我想回去删除程序的所有旧副本(保留它们是公司的一项政策,可以追溯到版本控制很常见之前,应该不再需要),但我需要一种方法来验证我是否可以生成完全相同的可执行文件,这比说“旧的一个来自于此提交所以这个是更好的应该是一样的。”

    我最初的想法是简单地对可执行文件进行MD5散列,将散列文件存储在源代码管理中,然后使用它,但是我遇到了一个我甚至无法解析的问题。

    似乎每次生成可执行文件时(方法:openproject)。文件>使X.exe)散列方式不同。我注意到每当项目以看似随机的方式打开时,visualbasic都会弄乱文件,但我不认为这会使它成为可执行文件,我也没有任何证据表明确实发生了这种情况。为了避免这种情况,我尝试在同一IDE会话中多次生成可执行文件并检查哈希值,但每次都不一样。

    那就是:

    1. 生成可执行文件
    2. 生成MD5校验和: md5sum X.exe > X.md5
    3. md5sum -c X.md5
    4. 生成新的可执行文件
    5. 验证新可执行文件的MD5: md5sum-c X.md5
    6. 验证失败,因为计算的校验和不匹配。

    提前感谢您的帮助!

    1 回复  |  直到 14 年前
        1
  •  13
  •   Mike Spross Alex Martelli    14 年前

    那几乎是不可能的。请继续阅读原因。

    编译器将赢得这场比赛,每次。。。

    原因之一是Windows用于EXE文件的PE(可移植可执行文件)格式包含一个时间戳,指示生成EXE的日期和时间,每当生成项目时,VB6编译器都会更新该时间戳。除了整个EXE的“main”时间戳外,EXE中的每个资源目录(其中图标、位图、字符串等存储在EXE中)也有一个时间戳,编译器在生成新的EXE时也会更新该时间戳。除此之外,EXE文件还有一个校验和字段,编译器将根据EXE的原始二进制内容重新计算该字段。由于时间戳更新为当前日期/时间,每次重新编译项目时,EXE的校验和也将更改。

    但是,但是…我发现这个非常酷的EXE编辑工具可以撤销这个编译器的诡计!

    有EXE编辑工具,如 PE Explorer ,它声称能够将EXE文件中的所有时间戳调整为固定时间。乍一看,您可能认为您可以将EXE的两个副本中的时间戳设置为相同的日期,并最终得到等效的文件(假设它们是从相同的源代码构建的),但事情比这更复杂:编译器可以自由地写出资源(字符串、图标、文件版本信息、,等)以不同的顺序编译代码,并且不能真正防止这种情况发生。资源作为独立的数据“块”存储,这些数据可以在生成的EXE中重新排列,而不会影响程序的运行时行为。

    如果这还不够,编译器可能会在未初始化内存的区域中构建EXE文件,因此EXE的某些部分可能包含编译器运行时内存中所有内容的位和片段,从而产生更多的差异。

    至于MD5。。。

    您没有误解MD5散列:MD5将 总是

    结论:源代码管理是你的朋友

    至于解决您当前的困境,我将留给您一个问题:将特定的EXE与特定版本的源代码相关联更像是一个策略问题,必须以某种方式强制执行,而不是其他任何事情。在没有任何上下文的情况下试图找出EXE来自哪个版本是不可靠的。你需要借助其他工具来追踪。例如,确保每个构建为EXE生成不同的版本号,并且该版本可以轻松地与版本控制系统中的特定修订/分支/标记/任何内容配对。为此,出现了一种“免费”的情况,一些开发人员使用源代码控制,而另一些开发人员使用“1997年的源代码副本”,我把它保存在我的网络文件夹中,因为它是 而且源代码管理是为娘娘腔无论如何“不会帮助使这更容易。我会让每个人都喝源代码控制Kool-Aid,并坚持立即创建构建的标准策略。

    每当我们构建项目时,我们的构建服务器(我们使用 Hudson Version Number Plugin 当我们发布一个构建时,我们使用版本号作为标记名在Subversion中创建一个标记。BuildServer将发布版本存档,因此我们始终可以获取提供给客户的特定EXE(和安装程序)。对于内部测试,我们可以选择从构建服务器中提取一个存档的EXE,或者直接告诉构建服务器从Subversion中创建的标记中重建EXE。

    我们也从来没有,从来没有,从来没有从构建服务器以外的任何机器向QA或客户发布过任何二进制文件。这可以防止“在我的机器上工作”的错误,并确保我们总是从源代码的“已知”副本进行编译(它只提取和构建Subversion存储库中的代码),并且我们总是可以将给定的二进制文件与创建它的代码的确切版本相关联。

        2
  •  0
  •   TAbdiukov miltonb    4 年前