我有一个DLL的源,我有一个编译版本,它躺在某个地方.
如果我编译源代码,它将具有与已编译版本不同的日期.
我怎么知道他们是否相同,只是在不同的时间被编辑?
要比较两个.dll文件,您可以使用ildasm或任何其他工具来交换IL代码.
我在dll文件中创建了一个嵌入式ildasm的示例,以便您可以在每台机器上使用它.当我们拆卸一个程序集时,我们检查执行的程序集文件夹中是否存在ildasm.exe文件,如果没有从我们的dll文件中提取文件.
使用ildasm文件,我们得到IL代码并将其保存到一个临时文件.
然后我们需要删除以下三行:
原文链接:https://www.f2er.com/windows/364073.html我在dll文件中创建了一个嵌入式ildasm的示例,以便您可以在每台机器上使用它.当我们拆卸一个程序集时,我们检查执行的程序集文件夹中是否存在ildasm.exe文件,如果没有从我们的dll文件中提取文件.
使用ildasm文件,我们得到IL代码并将其保存到一个临时文件.
然后我们需要删除以下三行:
MVID – 就像我之前写的那样,每个构建都生成一个唯一的GUID
图像基础(图像基础告诉我们,Windows加载程序将在内存中加载程序.) – 这与每个构建都不同
时间戳 – 运行ildasm的时间和日期
因此,我们读取临时文件内容,使用正则表达式删除这些行,然后将文件内容保存到同一个文件.
这是Disassembler类:
using System; using System.IO; using System.Linq; using System.Reflection; using System.Diagnostics; using System.Text.RegularExpressions; namespace FileHasher { public class Disassembler { public static Regex regexMVID = new Regex("//\\s*MVID\\:\\s*\\{[a-zA-Z0-9\\-]+\\}",RegexOptions.Multiline | RegexOptions.Compiled); public static Regex regexImageBase = new Regex("//\\s*Image\\s+base\\:\\s0x[0-9A-Fa-f]*",RegexOptions.Multiline | RegexOptions.Compiled); public static Regex regexTimeStamp = new Regex("//\\s*Time-date\\s+stamp\\:\\s*0x[0-9A-Fa-f]*",RegexOptions.Multiline | RegexOptions.Compiled); private static readonly Lazy<Assembly> currentAssembly = new Lazy<Assembly>(() => { return MethodBase.GetCurrentMethod().DeclaringType.Assembly; }); private static readonly Lazy<string> executingAssemblyPath = new Lazy<string>(() => { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); }); private static readonly Lazy<string> currentAssemblyFolder = new Lazy<string>(() => { return Path.GetDirectoryName(currentAssembly.Value.Location); }); private static readonly Lazy<string[]> arrResources = new Lazy<string[]>(() => { return currentAssembly.Value.GetManifestResourceNames(); }); private const string ildasmArguments = "/all /text \"{0}\""; public static string ILDasmFileLocation { get { return Path.Combine(executingAssemblyPath.Value,"ildasm.exe"); } } static Disassembler() { //extract the ildasm file to the executing assembly location ExtractFileToLocation("ildasm.exe",ILDasmFileLocation); } /// <summary> /// Saves the file from embedded resource to a given location. /// </summary> /// <param name="embeddedResourceName">Name of the embedded resource.</param> /// <param name="fileName">Name of the file.</param> protected static void SaveFileFromEmbeddedResource(string embeddedResourceName,string fileName) { if (File.Exists(fileName)) { //the file already exists,we can add deletion here if we want to change the version of the 7zip return; } FileInfo fileInfoOutputFile = new FileInfo(fileName); using (FileStream streamToOutputFile = fileInfoOutputFile.OpenWrite()) using (Stream streamToResourceFile = currentAssembly.Value.GetManifestResourceStream(embeddedResourceName)) { const int size = 4096; byte[] bytes = new byte[4096]; int numBytes; while ((numBytes = streamToResourceFile.Read(bytes,size)) > 0) { streamToOutputFile.Write(bytes,numBytes); } streamToOutputFile.Close(); streamToResourceFile.Close(); } } /// <summary> /// Searches the embedded resource and extracts it to the given location. /// </summary> /// <param name="fileNameInDll">The file name in DLL.</param> /// <param name="outFileName">Name of the out file.</param> protected static void ExtractFileToLocation(string fileNameInDll,string outFileName) { string resourcePath = arrResources.Value.Where(resource => resource.EndsWith(fileNameInDll,StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (resourcePath == null) { throw new Exception(string.Format("Cannot find {0} in the embedded resources of {1}",fileNameInDll,currentAssembly.Value.FullName)); } SaveFileFromEmbeddedResource(resourcePath,outFileName); } public static string GetDisassembledFile(string assemblyFilePath) { if (!File.Exists(assemblyFilePath)) { throw new InvalidOperationException(string.Format("The file {0} does not exist!",assemblyFilePath)); } string tempFileName = Path.GetTempFileName(); var startInfo = new ProcessStartInfo(ILDasmFileLocation,string.Format(ildasmArguments,assemblyFilePath)); startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.CreateNoWindow = true; startInfo.UseShellExecute = false; startInfo.RedirectStandardOutput = true; using (var process = System.Diagnostics.Process.Start(startInfo)) { string output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); if (process.ExitCode > 0) { throw new InvalidOperationException( string.Format("Generating IL code for file {0} Failed with exit code - {1}. Log: {2}",assemblyFilePath,process.ExitCode,output)); } File.WriteAllText(tempFileName,output); } RemoveUnnededRows(tempFileName); return tempFileName; } private static void RemoveUnnededRows(string fileName) { string fileContent = File.ReadAllText(fileName); //remove MVID fileContent = regexMVID.Replace(fileContent,string.Empty); //remove Image Base fileContent = regexImageBase.Replace(fileContent,string.Empty); //remove Time Stamp fileContent = regexTimeStamp.Replace(fileContent,string.Empty); File.WriteAllText(fileName,fileContent); } public static string DisassembleFile(string assemblyFilePath) { string disassembledFile = GetDisassembledFile(assemblyFilePath); try { return File.ReadAllText(disassembledFile); } finally { if (File.Exists(disassembledFile)) { File.Delete(disassembledFile); } } } } }
现在可以比较这两个IL代码的内容.另一个选项是生成这些文件的哈希码并进行比较. Hese是一个HashCalculator类:
使用系统;
使用System.IO;
使用System.Reflection;
namespace FileHasher { public class HashCalculator { public string FileName { get; private set; } public HashCalculator(string fileName) { this.FileName = fileName; } public string CalculateFileHash() { if (Path.GetExtension(this.FileName).Equals(".dll",System.StringComparison.InvariantCultureIgnoreCase) || Path.GetExtension(this.FileName).Equals(".exe",System.StringComparison.InvariantCultureIgnoreCase)) { return GetAssemblyFileHash(); } else { return GetFileHash(); } } private string GetFileHash() { return CalculateHashFromStream(File.OpenRead(this.FileName)); } private string GetAssemblyFileHash() { string tempFileName = null; try { //try to open the assembly to check if this is a .NET one var assembly = Assembly.LoadFile(this.FileName); tempFileName = Disassembler.GetDisassembledFile(this.FileName); return CalculateHashFromStream(File.OpenRead(tempFileName)); } catch(BadImageFormatException) { return GetFileHash(); } finally { if (File.Exists(tempFileName)) { File.Delete(tempFileName); } } } private string CalculateHashFromStream(Stream stream) { using (var readerSource = new System.IO.BufferedStream(stream,1200000)) { using (var md51 = new System.Security.Cryptography.MD5CryptoServiceProvider()) { md51.ComputeHash(readerSource); return Convert.ToBase64String(md51.Hash); } } } } }
您可以在我的博客上找到完整的应用程序源代码 – Compare two dll files programmatically