4 04 2014
Load a DLL at runtime – with hash-check
If you work with very dynamic code or external libraries or need to update your own libraries regularly, you sometimes need to load DLL’s at runtime.
With C# that’s very easy. We just have to use the Assembly-class from System.Reflection and call the static methods LoadFrom or LoadFile.
You can get a lot of information from the assembly class, but today we’ll just get a class we want, create an instance and call 2 methods.
First we’ll have to create the class we want to load:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
namespace ExternalClass { public class MyClass { public void DoSomething(String name){ Console.WriteLine("Hello " + name); } public void DoSomethingElse(){ Console.WriteLine("Else"); } } } |
After you compiled a DLL with this class, we can load and use it.
The following code is working with .Net 4 or higher because since then you can use “dynamic”.
Add it to a C# console program to see the resulting output.
1 2 3 4 5 6 |
var dll = Assembly.LoadFile(@"C:\project\ExternalClass.dll"); var class1Type = dll.GetType("ExternalClass.MyClass"); dynamic c = Activator.CreateInstance(class1Type); c.DoSomething("Peter Parker"); c.DoSomethingElse(); |
If you want to do the same with an older version of .Net, you have to use reflection. This is a bit more complicated, but also no problem.
The following code does exactly the same as the above:
1 2 3 4 5 6 |
var dll = Assembly.LoadFile(@"C:\project\ExternalClass.dll"); var class1Type = dll.GetType("ExternalClass.MyClass"); var v = Activator.CreateInstance(class1Type); class1Type.InvokeMember("DoSomething", BindingFlags.InvokeMethod, null, v, new object[] {"Peter Parker"}); class1Type.InvokeMember("DoSomethingElse", BindingFlags.InvokeMethod, null, v, new object[] {}); |
A problem with dynamic loading of DLLs is the potential risk of a manipulation. To prevent this you can check the hash of the dll.
But first you need a function to calculate it. I use MD5 for this example, but you can use what ever you want.
1 2 3 4 5 6 |
static byte[] generateMD5(String filename){ using (var stream = File.OpenRead(filename)) { return MD5.Create().ComputeHash(stream); } } |
Now you need to check the hash while loading the DLL. .Net provides a special method for this, LoadFrom. You can assign the hash and the used algorithm as parameter.
You’ll get a FileLoadException if the hash doesn’t match.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
static void Main() { String file = @"C:\project\ExternalClass.dll" byte [] hash = generateMD5(file); // hash[0]=5; //uncomment this to provoke an exception var dll = Assembly.LoadFrom(file,hash, AssemblyHashAlgorithm.MD5); var class1Type = dll.GetType("ExternalClass.MyClass"); dynamic c = Activator.CreateInstance(class1Type); c.DoSomething("Peter Parker"); c.DoSomethingElse(); } |
You can do a lot of stuff on top of that like zipping or encrypt your DLLs, but that’s up to you :-).
There are other things you can do with the Assembly-class too, you play with it.
And one final word of warning: If your dynamic code is wrong the compiler won’t tell you. You’ll just get an exception at runtime!
Limitation of Path.GetTempFileName