2010-04-29 36 views
10

मेरे पास एक डीएलएल का स्रोत है और मेरे पास इसके आसपास संकलित संस्करण का संकलित संस्करण है।मैं कैसे बता सकता हूं कि दो .NET DLL समान हैं या नहीं?

यदि मैं स्रोत संकलित करता हूं तो इसकी पहले से संकलित संस्करण की एक अलग तिथि होगी।

मैं कैसे बता सकता हूं कि वे वास्तव में वही हैं और केवल अलग-अलग समय पर संकलित किए गए हैं?

+0

बाइट्स की राशि?हालांकि यह अनुमानित सबसे सुरक्षित तरीका नहीं है, मुझे यकीन नहीं है कि – Bas

+0

यदि आपके मन में कोई निश्चित परिवर्तन है, और यह जांचना चाहते हैं कि किसी दिए गए डीएलएल फ़ाइल में है या नहीं, तो हमेशा .net परावर्तक होता है; इसके अलावा, कंगकन के उत्तर –

+0

@ बास के साथ जाएं: यह शायद सबसे अच्छी विधि है। @ डेविड: नेट परावर्तक कैसे मदद करेगा? – CJ7

उत्तर

-1

मूल तुलना डीएलएल के संस्करण और आकार की है। साथ ही, आप जांच सकते हैं कि संकलित डीएल की तारीख से परे किसी भी फ़ाइल में संशोधित दिनांक है या नहीं।

+0

मेरा प्रश्न देखें। यदि मैं स्रोत संकलित करता हूं तो इसकी पहले से संकलित संस्करण की एक अलग तिथि होगी। – CJ7

+0

@ क्रिएग: यदि आप सावधानी से पढ़ते हैं, तो मैंने उल्लेख किया है कि स्रोत कोड फ़ाइल की अंतिम संशोधित तिथि मूल डीएल की तारीख से परे नहीं होनी चाहिए। बेशक, यदि कोड किसी भी बदलाव के साथ सहेजा गया है, तो कार्यक्षमता में नहीं, तो संशोधन की तिथि भी बदलेगी। यह सुनिश्चित है कि यदि आप नए डीएल संकलित करेंगे तो एक अलग तारीख होगी। यह छोटा है। – Kangkan

+0

ठीक है, अब मैं आपका पॉइंट देखता हूं। हां, स्रोत फ़ाइलों की संशोधित तारीख को देखना अच्छा विचार होगा। – CJ7

0

आप डीईएल को डिस्सेम्बल करने के लिए .NET परावर्तक का उपयोग कर सकते हैं और इसे अंतिम कोड परिवर्तन से तुलना कर सकते हैं ताकि आप यह देख सकें कि वे समान हैं या नहीं। यदि वे हैं तो आप जानते हैं कि वे एक ही कोड पर आधारित हैं।

-1

बाइनरी मोड में फ़ाइलों की तुलना करें। भागो कमांड लाइन से निम्नलिखित:

fc /b file1.dll file2.dll 

कि आप जानते हैं कि फ़ाइलों को समान हैं करने देगा, लेकिन वे शायद नहीं होगा जब तक कि वे, ठीक उसी स्थिति में संकलित किया जाता है, जब से तुम स्रोत कोड है , संभव है।

+1

यह सच नहीं है, क्योंकि संकलक हमेशा बाइनरी में टाइमस्टैम्प और यादृच्छिक एमवीआईडी ​​डालता है। इसके अलावा आधार पता बदलने की संभावना है। –

2

NDepend और Plugin प्रतिबिंबक के लिए आप असेंबली की तुलना करने की अनुमति देते हैं।

16

दो .dll फ़ाइलों की तुलना करने के लिए आप आईएल कोड प्राप्त करने के लिए ildasm या किसी अन्य उपकरण का उपयोग कर सकते हैं। मैंने डीएलएल फ़ाइल में एम्बेडेड ildasm के साथ एक नमूना बनाया है ताकि आप इसे प्रत्येक मशीन पर उपयोग कर सकें। जब हम एक असेंबली को अलग करते हैं तो हम जांचते हैं कि ildasm.exe फ़ाइल निष्पादन असेंबली फ़ोल्डर में मौजूद है या नहीं और यदि हमारी डीएलएल फ़ाइल से फ़ाइल निकाली नहीं गई है। ildasm फ़ाइल का उपयोग करके हमें आईएल कोड मिलता है और इसे एक अस्थायी फ़ाइल में सहेजता है। फिर हम निम्नलिखित तीन पंक्तियों को हटाने की जरूरत:

MVID - जैसा कि मैंने लिखा था इससे पहले कि यह एक अद्वितीय हर साथ उत्पन्न GUID है निर्माण

छवि आधार (छवि आधार जहां कार्यक्रम के रूप में हमें बताता है विंडोज लोडर द्वारा स्मृति में लोड किया जाएगा) -। यह अलग है कि हर रूप में अच्छी तरह का निर्माण के साथ

समय तारीख मोहर - समय और तारीख जब ILDASM चलाया जाता है

इसलिए हम temp फ़ाइल सामग्री को पढ़ते हैं, regexes का उपयोग करके इन पंक्तियों को हटा दें, और फिर फ़ाइल सामग्री को उसी फ़ाइल में सहेजें।

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, 0, size)) > 0) 
       { 
        streamToOutputFile.Write(bytes, 0, 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); 
       } 
      } 
     } 
    } 
} 

अब आप इन दो आईएल कोड की सामग्री की तुलना कर सकते हैं: यहाँ Disassembler वर्ग है। एक और विकल्प इन फ़ाइलों के हैश कोड उत्पन्न करना और उनकी तुलना करना है। हेज़ एक हैशकलक्यूलेटर श्रेणी है: सिस्टम का उपयोग कर; 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

+0

आपकी सभी पोस्ट आपके ब्लॉग के लिंक हैं। –

+1

यह सुनिश्चित नहीं है कि इसे क्यों वोट दिया गया - यह एकमात्र उत्तर है जो वास्तव में – pappadog

+0

काम करता है जब मैंने इसका उपयोग किया तो मुझे पता चला कि समान डीएल में अभी भी ग्रिड में अंतर था। क्या यह guids में सभी परिवर्तनों को अनदेखा करना सुरक्षित है? – Daniel

संबंधित मुद्दे

 संबंधित मुद्दे