Das wird fast unmöglich sein. Lesen Sie weiter, um zu erfahren warum.
Der Compiler gewinnt jedes Mal dieses Spiel...
Wenn das gleiche Projekt hintereinander zweimal kompiliert wird, auch wenn keine Änderungen am Quellcode oder den Projekteinstellungen vorgenommen wurden, werden immer unterschiedliche ausführbare Dateien erstellt.
Ein Grund dafür ist, dass das PE (Portable Executable) Format, das Windows für EXE-Dateien verwendet, einen Zeitstempel enthält, der das Datum und die Uhrzeit angibt, an denen die EXE erstellt wurde. Dieser Zeitstempel wird vom VB6-Compiler aktualisiert, wenn das Projekt kompiliert wird. Neben dem "Haupt" Zeitstempel für die gesamte EXE hat jeder Ressourcenverzeichnis in der EXE (wo Symbole, Bitmaps, Zeichenfolgen usw. in der EXE gespeichert sind) auch einen Zeitstempel, den der Compiler aktualisiert, wenn eine neue EXE erstellt wird. Darüber hinaus haben EXE-Dateien auch ein Prüfsummenfeld, das der Compiler aufgrund des rohen binären Inhalts der EXE neu berechnet. Da die Zeitstempel auf das aktuelle Datum/Uhrzeit aktualisiert werden, ändert sich auch die Prüfsumme für die EXE jedes Mal, wenn ein Projekt neu kompiliert wird.
Aber...ich habe dieses wirklich coole EXE-Bearbeitungstool gefunden, das diese Compiler-Täuschung rückgängig machen kann!
Es gibt EXE-Bearbeitungstools wie PE Explorer, die behaupten, alle Zeitstempel in einer EXE-Datei auf eine feste Zeit einstellen zu können. Auf den ersten Blick könnten Sie denken, dass Sie einfach die Zeitstempel in zwei Kopien der EXE auf das gleiche Datum setzen könnten und äquivalente Dateien erhalten (vorausgesetzt, sie wurden aus dem gleichen Quellcode erstellt), aber die Dinge sind komplizierter: Der Compiler schreibt die Ressourcen (Zeichenfolgen, Symbole, Dateiversion Informationen usw.) jedes Mal in einer anderen Reihenfolge, wenn der Code kompiliert wird, und das können Sie nicht wirklich verhindern. Ressourcen werden als unabhängige "Chunks" von Daten gespeichert, die im resultierenden EXE neu angeordnet werden können, ohne das Laufzeitverhalten des Programms zu beeinflussen.
Wenn das nicht genug wäre, könnte der Compiler die EXE-Datei in einem Bereich nicht initialisierten Speichers erstellen, sodass bestimmte Teile der EXE Bits und Stücke von dem enthalten können, was zum Zeitpunkt des Kompilierens im Speicher war, was noch mehr Unterschiede schafft.
Betrachtung von MD5...
Sie haben das MD5-Hashing nicht falsch verstanden: MD5 wird immer bei gleicher Eingabe den gleichen Hash-Wert erzeugen. Das Problem hier ist jedoch, dass die Eingabe in diesem Fall (die EXE-Dateien) sich ständig ändert.
Fazit: Die Quellcodeverwaltung ist dein Freund
Um Ihr aktuelles Dilemma zu lösen, möchte ich Sie damit lassen: Die Zuordnung einer bestimmten EXE zu einer bestimmten Version des Quellcodes ist eher eine Angelegenheit der Richtlinie, die irgendwie durchgesetzt werden muss, als alles andere. Zu versuchen herauszufinden, welche EXE aus welcher Version stammt, ohne jeglichen Kontext, wird einfach nicht zuverlässig sein. Sie müssen dies mithilfe anderer Tools verfolgen. Beispielsweise können Sie sicherstellen, dass jede Erstellung eine andere Versionsnummer für Ihre EXE's erzeugt und dass diese Version einfach mit einer bestimmten Revision/Verzweigung/Markierung/whatever in Ihrem Versionsverwaltungssystem verknüpft werden kann. Zu diesem Zweck wird eine "Freifluss"-Situation, in der einige Entwickler die Quellcode-Verwaltung nutzen und andere "diese Kopie des Quellcodes von 1997, die ich in meinem Netzwerkordner aufbewahre, benutzen, weil es mein Code ist und Quellcodeverwaltung sowieso für Weicheier ist", dieses Problem nicht erleichtern. Ich würde jedem nahelegen, den Quellcode-Kool-Aid zu trinken und sich sofort an eine standardmäßige Richtlinie zur Erstellung von Builds zu halten.
Immer wenn wir Projekte erstellen, stellt unser Build-Server (wir verwenden Hudson) sicher, dass die kompilierte EXE-Version aktualisiert wird, um die aktuelle Build-Nummer einzuschließen (wir verwenden das Version Number Plugin und ein individuelles Build-Skript, um dies zu tun), und wenn wir einen Build veröffentlichen, erstellen wir einen Tag in Subversion mit dem Versionsnamen als Tag-Namen. Der Build-Server archiviert Freigabe-Builds, sodass wir immer die spezifische EXE (und das Setup-Programm) erhalten können, das einem Kunden gegeben wurde. Für interne Tests können wir wählen, eine archivierte EXE vom Build-Server abzurufen oder einfach den Build-Server auffordern, die EXE aus dem Tag, den wir in Subversion erstellt haben, neu zu erstellen.
Wir veröffentlichen auch niemals Binärdateien an QA oder an Kunden von einem anderen Computer als dem Build-Server aus. Dies verhindert "funktioniert auf meinem Computer" -Bugs und stellt sicher, dass wir immer von einer "bekannten" Kopie des Quellcodes kompilieren (es zieht und baut nur Code, der sich in unserem Subversion-Repository befindet) und dass wir immer eine bestimmte Binärdatei mit der genauen Version des Codes in Verbindung bringen können, aus der sie erstellt wurde.