如何判断两个.NET DLL是否相同?

前端之家收集整理的这篇文章主要介绍了如何判断两个.NET DLL是否相同?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个DLL的源,我有一个编译版本,它躺在某个地方.

如果我编译源代码,它将具有与已编译版本不同的日期.

我怎么知道他们是否相同,只是在不同的时间被编辑?

要比较两个.dll文件,您可以使用ildasm或任何其他工具来交换IL代码.
我在dll文件中创建了一个嵌入式ildasm的示例,以便您可以在每台机器上使用它.当我们拆卸一个程序集时,我们检查执行的程序集文件夹中是否存在ildasm.exe文件,如果没有从我们的dll文件提取文件.
使用ildasm文件,我们得到IL代码并将其保存到一个临时文件.
然后我们需要删除以下三行:

MVID – 就像我之前写的那样,每个构建都生成一个唯一的GUID

图像基础(图像基础告诉我们,Windows加载程序将在内存中加载程序.) – 这与每个构建都不同

时间戳 – 运行ildasm的时间和日期

因此,我们读取临时文件内容,使用正则表达式删除这些行,然后将文件内容保存到同一个文件.
这是Disassembler类:

  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Diagnostics;
  6. using System.Text.RegularExpressions;
  7.  
  8. namespace FileHasher
  9. {
  10. public class Disassembler
  11. {
  12. public static Regex regexMVID = new Regex("//\\s*MVID\\:\\s*\\{[a-zA-Z0-9\\-]+\\}",RegexOptions.Multiline | RegexOptions.Compiled);
  13. public static Regex regexImageBase = new Regex("//\\s*Image\\s+base\\:\\s0x[0-9A-Fa-f]*",RegexOptions.Multiline | RegexOptions.Compiled);
  14. public static Regex regexTimeStamp = new Regex("//\\s*Time-date\\s+stamp\\:\\s*0x[0-9A-Fa-f]*",RegexOptions.Multiline | RegexOptions.Compiled);
  15.  
  16. private static readonly Lazy<Assembly> currentAssembly = new Lazy<Assembly>(() =>
  17. {
  18. return MethodBase.GetCurrentMethod().DeclaringType.Assembly;
  19. });
  20.  
  21. private static readonly Lazy<string> executingAssemblyPath = new Lazy<string>(() =>
  22. {
  23. return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  24. });
  25.  
  26. private static readonly Lazy<string> currentAssemblyFolder = new Lazy<string>(() =>
  27. {
  28. return Path.GetDirectoryName(currentAssembly.Value.Location);
  29. });
  30.  
  31. private static readonly Lazy<string[]> arrResources = new Lazy<string[]>(() =>
  32. {
  33. return currentAssembly.Value.GetManifestResourceNames();
  34. });
  35.  
  36. private const string ildasmArguments = "/all /text \"{0}\"";
  37.  
  38. public static string ILDasmFileLocation
  39. {
  40. get
  41. {
  42. return Path.Combine(executingAssemblyPath.Value,"ildasm.exe");
  43. }
  44. }
  45.  
  46. static Disassembler()
  47. {
  48. //extract the ildasm file to the executing assembly location
  49. ExtractFileToLocation("ildasm.exe",ILDasmFileLocation);
  50. }
  51.  
  52. /// <summary>
  53. /// Saves the file from embedded resource to a given location.
  54. /// </summary>
  55. /// <param name="embeddedResourceName">Name of the embedded resource.</param>
  56. /// <param name="fileName">Name of the file.</param>
  57. protected static void SaveFileFromEmbeddedResource(string embeddedResourceName,string fileName)
  58. {
  59. if (File.Exists(fileName))
  60. {
  61. //the file already exists,we can add deletion here if we want to change the version of the 7zip
  62. return;
  63. }
  64. FileInfo fileInfoOutputFile = new FileInfo(fileName);
  65.  
  66. using (FileStream streamToOutputFile = fileInfoOutputFile.OpenWrite())
  67. using (Stream streamToResourceFile = currentAssembly.Value.GetManifestResourceStream(embeddedResourceName))
  68. {
  69. const int size = 4096;
  70. byte[] bytes = new byte[4096];
  71. int numBytes;
  72. while ((numBytes = streamToResourceFile.Read(bytes,size)) > 0)
  73. {
  74. streamToOutputFile.Write(bytes,numBytes);
  75. }
  76.  
  77. streamToOutputFile.Close();
  78. streamToResourceFile.Close();
  79. }
  80. }
  81.  
  82. /// <summary>
  83. /// Searches the embedded resource and extracts it to the given location.
  84. /// </summary>
  85. /// <param name="fileNameInDll">The file name in DLL.</param>
  86. /// <param name="outFileName">Name of the out file.</param>
  87. protected static void ExtractFileToLocation(string fileNameInDll,string outFileName)
  88. {
  89. string resourcePath = arrResources.Value.Where(resource => resource.EndsWith(fileNameInDll,StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
  90. if (resourcePath == null)
  91. {
  92. throw new Exception(string.Format("Cannot find {0} in the embedded resources of {1}",fileNameInDll,currentAssembly.Value.FullName));
  93. }
  94. SaveFileFromEmbeddedResource(resourcePath,outFileName);
  95. }
  96.  
  97. public static string GetDisassembledFile(string assemblyFilePath)
  98. {
  99. if (!File.Exists(assemblyFilePath))
  100. {
  101. throw new InvalidOperationException(string.Format("The file {0} does not exist!",assemblyFilePath));
  102. }
  103.  
  104. string tempFileName = Path.GetTempFileName();
  105. var startInfo = new ProcessStartInfo(ILDasmFileLocation,string.Format(ildasmArguments,assemblyFilePath));
  106. startInfo.WindowStyle = ProcessWindowStyle.Hidden;
  107. startInfo.CreateNoWindow = true;
  108. startInfo.UseShellExecute = false;
  109. startInfo.RedirectStandardOutput = true;
  110.  
  111. using (var process = System.Diagnostics.Process.Start(startInfo))
  112. {
  113. string output = process.StandardOutput.ReadToEnd();
  114. process.WaitForExit();
  115.  
  116. if (process.ExitCode > 0)
  117. {
  118. throw new InvalidOperationException(
  119. string.Format("Generating IL code for file {0} Failed with exit code - {1}. Log: {2}",assemblyFilePath,process.ExitCode,output));
  120. }
  121.  
  122. File.WriteAllText(tempFileName,output);
  123. }
  124.  
  125. RemoveUnnededRows(tempFileName);
  126. return tempFileName;
  127. }
  128.  
  129. private static void RemoveUnnededRows(string fileName)
  130. {
  131. string fileContent = File.ReadAllText(fileName);
  132. //remove MVID
  133. fileContent = regexMVID.Replace(fileContent,string.Empty);
  134. //remove Image Base
  135. fileContent = regexImageBase.Replace(fileContent,string.Empty);
  136. //remove Time Stamp
  137. fileContent = regexTimeStamp.Replace(fileContent,string.Empty);
  138. File.WriteAllText(fileName,fileContent);
  139. }
  140.  
  141. public static string DisassembleFile(string assemblyFilePath)
  142. {
  143. string disassembledFile = GetDisassembledFile(assemblyFilePath);
  144. try
  145. {
  146. return File.ReadAllText(disassembledFile);
  147. }
  148. finally
  149. {
  150. if (File.Exists(disassembledFile))
  151. {
  152. File.Delete(disassembledFile);
  153. }
  154. }
  155. }
  156. }
  157. }

现在可以比较这两个IL代码内容.另一个选项是生成这些文件的哈希码并进行比较. Hese是一个HashCalculator类:
使用系统;
使用System.IO;
使用System.Reflection;

  1. namespace FileHasher
  2. {
  3. public class HashCalculator
  4. {
  5. public string FileName { get; private set; }
  6.  
  7. public HashCalculator(string fileName)
  8. {
  9. this.FileName = fileName;
  10. }
  11.  
  12. public string CalculateFileHash()
  13. {
  14. if (Path.GetExtension(this.FileName).Equals(".dll",System.StringComparison.InvariantCultureIgnoreCase)
  15. || Path.GetExtension(this.FileName).Equals(".exe",System.StringComparison.InvariantCultureIgnoreCase))
  16. {
  17. return GetAssemblyFileHash();
  18. }
  19. else
  20. {
  21. return GetFileHash();
  22. }
  23. }
  24.  
  25. private string GetFileHash()
  26. {
  27. return CalculateHashFromStream(File.OpenRead(this.FileName));
  28. }
  29.  
  30. private string GetAssemblyFileHash()
  31. {
  32. string tempFileName = null;
  33. try
  34. {
  35. //try to open the assembly to check if this is a .NET one
  36. var assembly = Assembly.LoadFile(this.FileName);
  37. tempFileName = Disassembler.GetDisassembledFile(this.FileName);
  38. return CalculateHashFromStream(File.OpenRead(tempFileName));
  39. }
  40. catch(BadImageFormatException)
  41. {
  42. return GetFileHash();
  43. }
  44. finally
  45. {
  46. if (File.Exists(tempFileName))
  47. {
  48. File.Delete(tempFileName);
  49. }
  50. }
  51. }
  52.  
  53. private string CalculateHashFromStream(Stream stream)
  54. {
  55. using (var readerSource = new System.IO.BufferedStream(stream,1200000))
  56. {
  57. using (var md51 = new System.Security.Cryptography.MD5CryptoServiceProvider())
  58. {
  59. md51.ComputeHash(readerSource);
  60. return Convert.ToBase64String(md51.Hash);
  61. }
  62. }
  63. }
  64. }
  65. }

您可以在我的博客上找到完整的应用程序源代码Compare two dll files programmatically

猜你在找的Windows相关文章