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

8 浏览
0 Comments

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

我有一个DLL的源代码,并且还有一个已经编译好的版本放在某个地方。

如果我编译源代码,生成的文件日期会和已经编译好的版本不同。

我怎样才能确定它们是否实际上是相同的,只是在不同的时间编译的呢?

0
0 Comments

在开发.NET应用程序时,经常会遇到需要比较两个.NET DLL文件是否相同的情况。这种需求可能出现在多个场景中,例如在版本控制中确保没有误提交,或者在部署应用程序时确保正确地使用了最新的DLL文件。那么,我们该如何判断两个.NET DLL文件是否相同呢?下面将介绍一种方法来解决这个问题。

我们可以使用.NET反编译工具.NET Reflector来反汇编(Disassemble)这两个DLL文件,并将它们与最后一次代码更改进行比较。如果它们是相同的,那么我们就可以确定它们是基于相同的代码生成的。

具体的解决方法如下:

1. 首先,确保已经安装了.NET Reflector工具。如果没有安装,可以从官方网站下载并安装。

2. 打开.NET Reflector,点击菜单栏的“File”选项,选择“Open Assembly”来打开第一个DLL文件。

3. 在.NET Reflector的界面中,可以看到反汇编后的DLL文件的代码。将其复制到一个文本编辑器中,保存为一个文本文件(例如,file1.txt)。

4. 重复步骤2和3,将第二个DLL文件也保存为另一个文本文件(例如,file2.txt)。

5. 使用文件比较工具(例如,WinMerge)打开这两个文本文件,将它们进行比较。如果两个文件完全相同,那么这两个DLL文件就是相同的。

通过以上步骤,我们可以很方便地比较两个.NET DLL文件是否相同。这种方法适用于任何.NET语言编写的DLL文件,无论是C#、VB.NET还是其他.NET语言。

需要注意的是,由于.NET Reflector是一个第三方工具,可能会有一些局限性和兼容性问题。因此,在使用它进行反汇编和比较之前,建议先了解其使用方法和限制。

总结起来,通过使用.NET Reflector工具来反汇编和比较两个.NET DLL文件,我们可以快速准确地判断它们是否相同。这种方法简单易行,适用于.NET开发人员在日常工作中的各种场景。希望以上内容对于解决这个问题有所帮助。

0
0 Comments

为了判断两个.NET DLL文件是否相同,可以使用NDepend和Reflector的插件来比较这两个程序集。

在.NET开发中,一个程序集(assembly)是.NET应用程序的基本组成单位,它通常以DLL或EXE文件的形式存在。有时候我们需要判断两个程序集是否相同,这可能是因为需要比较两个版本之间的差异,或者需要验证一个程序集是否被篡改过。

一种常见的解决方法是使用NDepend。NDepend是一个.NET静态分析工具,它可以帮助开发人员在开发过程中进行代码分析和验证。NDepend提供了一个功能,可以比较两个程序集之间的差异。通过使用NDepend,开发人员可以快速判断两个程序集是否相同,并查看它们之间的差异。

另一种解决方法是使用Reflector的插件。Reflector是一个.NET反编译工具,它可以将.NET程序集反编译为可读的源代码。Reflector提供了一个插件系统,可以扩展其功能。有一些插件可以用于比较两个程序集之间的差异。通过使用Reflector及其插件,开发人员可以方便地比较两个程序集,并查看它们之间的差异。

总之,为了判断两个.NET DLL文件是否相同,可以使用NDepend或Reflector的插件来比较它们。这些工具可以帮助开发人员快速判断两个程序集之间的差异,并验证它们是否相同。

0
0 Comments

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

要比较两个.dll文件,您可以使用ildasm或任何其他用于获取IL代码的工具。

我创建了一个示例,其中包含了ildasm的嵌入式dll文件,这样您就可以在任何机器上使用它。当我们反汇编一个程序集时,我们检查执行程序集文件夹中是否存在ildasm.exe文件,如果不存在,则从我们的dll文件中提取出该文件。

使用ildasm文件,我们获取IL代码并将其保存到临时文件中。

然后,我们需要删除以下三行:

MVID-正如我之前所写,这是每次构建时生成的唯一GUID

Image Base(图像基址告诉我们程序将在内存中由Windows加载器加载的位置)-这也是每次构建时不同的

Time-date stamp-ildasm运行时的时间和日期

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

下面是反汇编器类:

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 currentAssembly = new Lazy(() =>
        {
            return MethodBase.GetCurrentMethod().DeclaringType.Assembly;
        });
        private static readonly Lazy executingAssemblyPath = new Lazy(() =>
        {
            return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        });
        private static readonly Lazy currentAssemblyFolder = new Lazy(() =>
        {
            return Path.GetDirectoryName(currentAssembly.Value.Location);
        });
        private static readonly Lazy arrResources = new Lazy(() =>
        {
            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);
        }
        /// 
        /// Saves the file from embedded resource to a given location.
        /// 
        /// Name of the embedded resource.
        /// Name of the file.
        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();
            }
        }
        /// 
        /// Searches the embedded resource and extracts it to the given location.
        /// 
        /// The file name in DLL.
        /// Name of the out file.
        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代码的内容。另一种选择是生成这些文件的哈希码并进行比较。这是一个HashCalculator类:

using System;
using System.IO;
using 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);
                }
            }
        }
    }
}

您可以在我的博客上找到完整的应用程序源代码-比较两个dll文件编程。

0