Determining Whether a File Is an Assembly
A file is an assembly if and only if it's managed and it contains an Assembly entry in its CLR metadata.
Determining by hand
A fast way to determine whether a file is an assembly is to run ildasm.exe on it. If it immediately gives an error saying that it may not be a PE file, then it's not a managed file. But, if it is an assembly, then ildasm will show an entry for the Assembly definition (“.assembly“ in the MANIFEST window or at the bottom of the original window).
Determining programmatically
From unmanaged code, you can call GetAssemblyFromScope() on the IMetaDataAssemblyImport interface for the file. If it returns S_OK, it's an assembly. If it returns CLDB_E_RECORD_NOTFOUND, it's not an assembly.
From managed code, if AssemblyName.GetAssemblyName(), Assembly.Load*(), etc. succeeds when given that file, then it's an assembly. If the load failed with a BadImageFormatException, then it may not be an assembly. There are other reasons, however, why that exception may have been thrown (maybe it's an assembly but could not be loaded because it has an incorrect format). Coming soon in v2, if the hresult for BadImageFormatException is COR_E_ASSEMBLYEXPECTED, then it's because it's not an assembly. Catch the exception and call System.Runtime.InteropServices.Marshal.GetHRForException() to get its hresult to find out.
Note that this assumes that you are not concerned about performance. If you are concerned about that, then the way to optimize for it is to not try to determine whether files are assemblies at runtime at all. (Some people are concerned about the exception that is thrown if the file is not an assembly. They overlook that in order to determine that it is not one, it has to be loaded and then thrown away, which can be even more expensive than catching an exception!) Instead, require that only assemblies are given to you. Then, if a file is not an assembly, it will be an exceptional situation. That way, you avoid the bad perf of both the exception and the unnecessary file loading.
Comments
- Anonymous
March 18, 2004
How can I check if the file is an assembly WITHOUT loading an assembly from managed code? For example, to present user with list of available plug-ins. - Anonymous
March 18, 2004
If you call AssemblyName.GetAssemblyName() (except in v1.0 SP2 - will be fixed in SP3), it will return an AssemblyName if it's a valid assembly, or throw a BadImageFormatException if not. The file will be loaded and then immediately released after data is retrieved. So, it won't cause the assembly to remain locked.
Another option is to do the loading in a separate AppDomain, which you unload when you're finished. - Anonymous
March 21, 2004
Why do I have to use a way that returns an exception if it fails?
Why not return a boolean for an Assembly.IsAssemblyFile(string) method or something?
Exceptions cost too much... - Anonymous
March 22, 2004
Opening the file when it will not later be used is not optimal for performance, either. IMHO, if perf is a concern, then the IsAssemblyFile() question should not be asked by the app at all. That app should make it so that they can assume it's an assembly (or that it's not), without having to test it. One way to do that is by having the user specify the assembly or assemblies that s/he cares about. In that case, if it turns out to not be an assembly when it's supposed to be, then it's an 'exceptional' situation, and can fail as appropriate. - Anonymous
March 22, 2004
I agree with you when talking about normal situations. However, a situation I can present you with as a good example is when you want to list all assemblies in a certain directory.
Listing .DLL and .EXE files isn't enough, since you can't be sure they're all assembly files.
This situation could benefit from such a method, since there is an iteration on the files and an exception slows down the process. - Anonymous
July 25, 2005
I have assemblies that are strong named and therefore MUST be managed. When I run Ildasm.exe, I get the PE exception. Therefore, I don't believe that your blog entry is accurate as perfectly valid, strong named, managed assemblies also get the PE exception. If you have further comments on this, I would greatly appreciate them as I am trying to find an accurate way to determine whether an assembly is managed or not. Thanks and I like your blog! - Anonymous
July 26, 2005
Omer: My point was that I recommend a design where needing to check all the files in a dir is unnecessary. So, yes, that is a situation where you would want an IsAssemblyFile(), but my point was that you should avoid that situation in the first place, for the reasons I gave in my earlier responses.
Joseph: It's hard to tell what caused the exception without more info. But, it sounds so far that the file is corrupt, not a valid, strongly-named, managed assembly, or else ildasm would have been able to load it. Try running peverify.exe on it. - Anonymous
November 02, 2005
I wrote this code through which we can determine programmatically whether a file is a .NET assembly or not - all managed way.
http://www.geekswithblogs.com/rupreet/archive/2005/11/02/58873.aspx