如何使用C#判断一个文件是否为程序集

程序集是经由编译器编译得到的,供 CLR 进一步编译执行的那个中间产物。它一般表现为 .dll 或者是 .exe 的格式,但是要注意,它们跟普通意义上的 WIN32 可执行程序是完全不同的东西,程序集必须依靠 CLR 才能顺利执行。程序集是 .NET 编程的基本组成部分。.

如何手动确认一个文件是否为程序集

  1. 启动 IL 反汇编程序(如 Ildasm.exe 或者 ILSpy)。

  2. 载入你想测试的文件。

  3. 如果可以正常载入显示了程序集信息,则说明为程序集。如果提示 “that the file is not a portable executable (PE) file” 则表示该文件不是程序集文件。

如何使用编程方式判断一个文件是否为程序集

使用 AssemblyName

  1. 调用 AssemblyName.GetAssemblyName 方法,传递测试文件的完整路径。

  2. 如果引发 BadImageFormatException 异常,则该文件不是程序集。

此示例测试 DLL 是否为程序集:

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

static class ExampleAssemblyName
{
    public static void CheckAssembly()
    {
        try
        {
            string path = Path.Combine(
                RuntimeEnvironment.GetRuntimeDirectory(),
                "System.Net.dll");

            AssemblyName testAssembly = AssemblyName.GetAssemblyName(path);
            Console.WriteLine("Yes, the file is an assembly.");
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("The file cannot be found.");
        }
        catch (BadImageFormatException)
        {
            Console.WriteLine("The file is not an assembly.");
        }
        catch (FileLoadException)
        {
            Console.WriteLine("The assembly has already been loaded.");
        }
    }

    /* Output:
    Yes, the file is an assembly.  
    */
}

GetAssemblyName 方法会先加载测试文件,然后在读取信息后释放。

使用 PEReader

  1. 安装 NuGet 包 :System.Reflection.Metadata

  2. 创建一个 System.IO.FileStream 实例,用于从测试文件读取数据。

  3. 创建一个 System.Reflection.PortableExecutable.PEReader 实例,并把文件流传递给构造函数。、

  4. 检查 HasMetadata 属性值。如果为 false,则该文件不是程序集。

  5. 调用 PEReader 实例的 GetMetadataReader 方法,创建一个元数据读取器。

  6. 检查 IsAssembly 属性值。如果为 false,则该文件不是程序集。

与 GetAssemblyName 方法不同,PEReader 不会在本机可移植可执行文件(PE)上引发异常。这使您能够在需要检查此类文件时避免异常导致的额外性能成本。如果文件不存在或不是PE文件,您仍然需要处理异常。

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;

static class ExamplePeReader
{
    static bool IsAssembly(string path)
    {
        using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        // Try to read CLI metadata from the PE file.
        using var peReader = new PEReader(fs);

        if (!peReader.HasMetadata)
        {
            return false; // File does not have CLI metadata.
        }

        // Check that file has an assembly manifest.
        MetadataReader reader = peReader.GetMetadataReader();
        return reader.IsAssembly;
    }

    public static void CheckAssembly()
    {
        string path = Path.Combine(
                RuntimeEnvironment.GetRuntimeDirectory(),
                "System.Net.dll");

        try
        {
            if (IsAssembly(path))
            {
                Console.WriteLine("Yes, the file is an assembly.");
            }
            else
            {
                Console.WriteLine("The file is not an assembly.");
            }
        }
        catch (BadImageFormatException)
        {
            Console.WriteLine("The file is not an executable.");
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("The file cannot be found.");
        }
    }

    /* Output:
    Yes, the file is an assembly.  
    */
}