Best way to check if a DLL file is a CLR assembly in C#

Viewed 16341

What is the best way to check if a DLL file is a Win32 DLL or if it is a CLR assembly. At the moment I use this code

    try
    {
        this.currentWorkingDirectory = Path.GetDirectoryName(assemblyPath);

        //Try to load the assembly.
        assembly = Assembly.LoadFile(assemblyPath);

        return assembly != null;
    }
    catch (FileLoadException ex)
    {
        exception = ex;
    }
    catch (BadImageFormatException ex)
    {
        exception = ex;
    }
    catch (ArgumentException ex)
    {
        exception = ex;
    }
    catch (Exception ex)
    {
        exception = ex;
    }

    if (exception is BadImageFormatException)
    {
        return false;
    }

But I like to check before loading because I do not want those exceptions (time).

Is there a better way?

8 Answers

My current reputation is insufficient to comment directly on Jeremy's answer which works well for 32-bit DLLs. But I had to refine it for 64-bit DLLs, which appear to have more Windows-specific COFF fields.

As described by Microsoft, the COFF Magic number indicates if the format is PE32 (32-bit) or PE32+ (64-bit). If the latter, then the offset to the Data Directories is 112 bytes instead of 96.

// After the COFF header, the first COFF field is a Magic Number.
UInt16 coffMagic = reader.ReadUInt16();

// Skip remaining fields to reach data directories.  See:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-image-only
if (coffMagic == 0x010B)
{
    // It's a 32-bit DLL.  96 bytes of COFF fields.
    // Subtract 2 for the magic number we just read.
    fs.Position += (96 - 2);
}
else if (coffMagic == 0x020B)
{
    // It's a 64-bit DLL.  112 bytes of COFF fields.
    // Subtract 2 for the magic number we just read.
    fs.Position += (112 - 2);
}

Update 2020:

This should be the easiest way to detect if the dll is a .Net library:

public bool IsNetAssembly(string fileName)
{
    try
    {
        AssemblyName.GetAssemblyName(fileName);
    }
    catch (BadImageFormatException)
    {
        // not a .Net Assembly
         return false;
    }
    
    return true;
}
Related