Home > Mobile >  Is there a way to avoid BadImageFormatException on Assembly.Load by pre-analyzing
Is there a way to avoid BadImageFormatException on Assembly.Load by pre-analyzing

Time:09-06

I have an application, that loads all the .dlls the user puts into a special directory. If they are created wrong (x86,x64) or something else, an BadImageFormatException is thrown. Thats ok, but I don't like avoid exceptions. So the question is:

Is there a way to analyse the file in advance to NOT get an exception?

  • Check if it's the right platform target
  • Check if it's unmanaged..
    • other possible issues.

Main goal is to avoid the exception. It would also be OK to get a bool that tells, if it will work.

Current Code:

    private Assembly TryLoadAssmbly(string file)
    {
        Assembly result;

        try
        {
            result = Assembly.LoadFile(file);
        }
        catch (BadImageFormatException exc)
        {
            Log.Error($"File \"{file}\" could not be loaded");
            result = null;
        }

        return result;
    }

CodePudding user response:

I am not sure if it's worthy of the effort BUT you could use PEReader:

static bool IsLoadableManagedAssembly(string assemblyPath) {
   using var reader = new PEReader(new StreamReader(assemblyPath));
   ...
}

First of all exclude files without metadata, they're not assemblies for sure:

if (!reader.HasMetadata)
   return false;

Now you can check if it's 32 or 64 bit...and things get a bit more complicate. There is a nice reader.PEHeaders.PEHeader.Magic you can use to check if the file is 64 bit only: PEMagic.PE32Plus (and you can stop here if your application is 32 bit only.

Still reading? Then you're targeting Any CPU or X64. You have this in the COFF object:

bool mightBe64 = reader.PEHeaders.CoffHeader.Machine == Machine.IA64
   || reader.PEHeaders.CoffHeader.Machine == Machine.Unknown;

if (Environment.Is64BitProcess != mightBe64)
   return false;

Now we can handle Any CPU with "required 32 bit":

bool requires32 = reader.PEHeaders.CorHeader.Flags.HasFlag(CorFlags.Requires32Bit);
if (Environment.Is64BitProcess && requires32)
   return false;

Note that you could (should?) use CorFlags.ILOnly also for Any CPU.

There is also a Characteristics.Bit32Machine in CoffHeader.Characteristics but I am not sure if could be anything not already covered.


In the top of everything...you will still need to handle BadImageFormatException because the file could be invalid or we missed something else here.


Did you consider caching the result of your search so you won't need to "try" to load them after the first time?


References:

  • Related