Checking if a file is a .NET assembly

2019-04-20 04:18发布

问题:

I've seen some methods of checking if a PEFile is a .NET assembly by examining the binary structure.

Is that the fastest method to test multiple files? I assume that trying to load each file (e.g. via Assembly.ReflectionOnlyLoad) file might be pretty slow since it'll be loading file type information.

Note: I'm looking for a way to check files programmatically.

回答1:

Maybe this helps

from https://web.archive.org/web/20110930194955/http://www.grimes.demon.co.uk/dotnet/vistaAndDotnet.htm

Next, I check to see if it is a .NET assembly. To do this I check to see if the file contains the CLR header. This header contains important information about the location of the .NET code in the file and the version of the framework that was used to write that code. The location of this header is given in the file's Data Directory table. If the data directory item has zero values then the file is unmanaged, if it has non-zero values then the file is a .NET assembly.

You can test this yourself using the dumpbin utility with the /headers switch. This utility will print the various headers in a file on the command line. At the end of the Optional Header Values you'll see a list of the Data Directories (there will always be 16 of them) and if the COM Descriptor Directory has a non-zero location it indicates that the file is a .NET assembly. The contents of the CLR header can also be listed using the /clrheader switch (if the file is unmanaged this will show no values). XP tests for the CLR header when it executes a file and if the CLR header is present it will initialize the runtime and pass the entry point of the assembly to the runtime, so that the file runs totally within the runtime.



回答2:

I guess Stormenet's answer isn't technically programmatic, so I'll seperate my response into an answer.

For best performance, nothing is going to beat opening the file(s) with a StreamReader, reading the first (n) bytes and checking for the .NET file signature data structures in the byte stream.

Pretty much the same way you'd verify something is a DOS executable:

http://en.wikipedia.org/wiki/DOS_executable

Look for the "MZ" header bytes, which also happen to be the initials of Mark Zbikowski, one of the developers of MS-DOS..



回答3:

In the past I've used AssemblyName.GetAssemblyName(), which throws an exception if it's not a managed assembly. However, I've never performance tested it, so I can't say how fast it is.



回答4:

The first link there is going to be the fastest and simplest method of checking (the PE file header one). You're correct in assuming that calling Assembly.ReflectionOnlyLoad is going to be pretty slow.