views:

256

answers:

8

How do you check if a assembly loaded is a valid .NET assembly? I currently have this code but unmanaged DLL's throw a BadImageFormatException.

 string[] filepaths = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.AllDirectories);
        List<Type> potentialEffects = new List<Type>();
        foreach (string filepath in filepaths)
        {
            Assembly a = Assembly.LoadFile(filepath);
            potentialEffects.AddRange(a.GetTypes());
        }
+10  A: 

You could simply catch this exception?

Also see this article here: http://blogs.msdn.com/suzcook/archive/2004/03/17/determining-whether-a-file-is-an-assembly.aspx Just catch the exception. Checking would be a lot more costly than just assuming that a file is an valid assembly.

Sebastian P.R. Gingter
try catch is slow, was wondering if it was possible to use a conditional statment
Euclid
Euclid: You are micro-optimizing. The cost of throwing `BadImageFormatException` is insignificant in comparison to actual loading.
Mehrdad Afshari
There is a way that requires P/Invoke (which is also slow). On MSDN Blogs there is quite a good article on that: http://blogs.msdn.com/suzcook/archive/2004/03/17/determining-whether-a-file-is-an-assembly.aspx
Sebastian P.R. Gingter
Besides, the alternative is to parse the PE format and check for the CLR header, that ain't a cheap operation in terms of perf either. And ridiculous overhead compared to catching the BadImageFormatException.
Wim Hollebrandse
Catching the exception is clean and easy. Unless performance is a significant issue for you, this is a no-brainer.
Programming Hero
try catch is slow in the _general_ case, but usually only becomes an issue when you have to do it a lot. Even still, this seems like it may be the exception (no pun intended) that proves the rule. How many assemblies are you planning on loading? Simplicity has a value of its own.
Jim Leonardo
+2  A: 

The exception is your best way of validating the assembly.

Remember, it's not just the manager/unmanaged checks that are going on when you load an assembly. There may be signature checks, platform checks (32bit vs 64bit). These things can also cause exceptions to be thrown.

You're better off letting the framework do it's job.

If you're loading managed code that forms part of an add-in system (hence you're looking at all the dlls in a folder) then I would suggest you pick a naming convention, or use a seperate addin folder where you don't expect to find unmanaged code.

Martin Peck
+1  A: 

An unmanaged DLL is not a valid .NET assembly. Try to load the "assembly" and catch exceptions on failure. If an exception is not thrown, it's okay to go.

Jason
+1  A: 

If you want to check it from C# you can add a Try Catch.

Or you can use the peverify.exe tool provided with the .net framework to know if a dll is a valid assembly.

PatriceVB
Launching a peverify process (which ships only with the SDK, not with the redistributable) seems a bit heavy weight for this kind of test :)
Jb Evain
A: 

I've seen BadImageFormatException thrown when trying to load x86 asms from x64 asms and vice versa.

http://blogs.msdn.com/arvindsh/archive/2009/06/21/tip-of-the-day-an-attempt-was-made-to-load-a-program-with-an-incorrect-format-net-p-invoke-issue.aspx

pattersonc
A: 

Take a look at the Activator class.

Wrapping this technique in a try/catch block can help you trap all manner of invalid types, not just .NET assemblies but many other runtime violations as well.

Aliixx
+4  A: 

I have this piece of code to check whether a file is a PE file and a managed assembly. It's quite easy to use:

var files = Directory.GetFiles (
    Directory.GetCurrentDirectory (),
    "*.dll", SearchOption.AllDirectories);

var potentialEffects = new List<Type> ();

foreach (var file in files) {
    if (!Image.IsAssembly (file))
     continue;

    var assembly = Assembly.LoadFile (filepath);
    potentialEffects.AddRange (assembly.GetTypes ());
}

For what it's worth, a little benchmark shows that it's twice as fast on my machine compared to the exception Assembly.LoadFrom will trigger. On the other hand, it will lose a bit of time in the valid case. So it's a matter of timing the average case.

Jb Evain