简体   繁体   English

有没有办法通过预先分析来避免 Assembly.Load 上的 BadImageFormatException

[英]Is there a way to avoid BadImageFormatException on Assembly.Load by pre-analyzing

I have an application, that loads all the.dlls the user puts into a special directory.我有一个应用程序,它将用户放入一个特殊目录的所有 .dll 加载。 If they are created wrong (x86,x64) or something else, an BadImageFormatException is thrown.如果它们创建错误 (x86,x64) 或其他内容,则会引发 BadImageFormatException。 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;
    }

I am not sure if it's worthy of the effort BUT you could use PEReader :我不确定这是否值得努力,但您可以使用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.现在您可以检查它是 32 位还是 64 位......事情变得更复杂了。 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.有一个不错的reader.PEHeaders.PEHeader.Magic可用于检查文件是否仅为 64 位: PEMagic.PE32Plus (如果您的应用程序仅为 32 位,您可以在此处停止。

Still reading?还在读书? Then you're targeting Any CPU or X64.然后你的目标是任何 CPU或 X64。 You have this in the COFF object:你在 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":现在我们可以处理任何具有“所需 32 位”的 CPU

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 .请注意,您也可以(应该?)将CorFlags.ILOnly用于Any CPU

There is also a Characteristics.Bit32Machine in CoffHeader.Characteristics but I am not sure if could be anything not already covered. CoffHeader.Characteristics中还有一个Characteristics.Bit32Machine但我不确定是否有任何尚未涵盖的内容。


In the top of everything...you will still need to handle BadImageFormatException because the file could be invalid or we missed something else here.最重要的是......您仍然需要处理BadImageFormatException因为文件可能无效或者我们在这里遗漏了其他内容。


Did you consider caching the result of your search so you won't need to "try" to load them after the first time?您是否考虑过缓存搜索结果,以便在第一次之后无需“尝试”加载它们?


References:参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM