blah blah blah is here! blah blah » Close

up1down
link

I have a .dll that I want to generate a hash from, both at a class level and a global hash that represents the entire assembly.

So the idea is that I will know if the assembly has changed, and I can then also figure out if a given class has changed.

So for a class level hash, I want the hash to be built using all the public properties and their types.

Then I would just loop through all the classes and then create a global hash from all the individual class hashes.

last answered one year ago

1 answers

link

Here's some basic code to do something like that.

You don't really need to calculate a hash for the assembly as a whole because, if a class has changed, then so too has the assembly.

One problem is that the Type.GetProperties() method doesn't guarantee the order in which the properties will be returned. To deal with this, I've sorted the properties into alphabetic order first before calculating the hash.

Even if a class doesn't contain any public properties (static or instance), a hash will still be calculated based on the (fully qualified) type name.

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;

class Program
{
static void Main()
{
string filePath = "test.dll";
Assembly assem = Assembly.LoadFrom (filePath);
Type[] types = assem.GetTypes();

foreach(Type t in types)
{
if (t.IsClass && t.IsPublic)
{
PropertyInfo[] pia = t.GetProperties();
List<string> propNames = new List<string>();
foreach(PropertyInfo pi in pia)
{
propNames.Add(pi.Name +" " + pi.PropertyType);
}
propNames.Sort(); // to guard against property order changing
propNames.Insert(0, t.FullName); // insert type name at beginning
File.WriteAllLines("temp.txt", propNames.ToArray());
byte[] hash;
using (Stream fs = File.OpenRead("temp.txt"))
{
hash = MD5.Create().ComputeHash(fs);
}
string fileName = "hash-" + t.FullName + ".bin";
if (File.Exists(fileName))
{
byte[] originalHash = File.ReadAllBytes(fileName);
for(int i = 0; i < hash.Length; i++)
{
if (hash[i] != originalHash[i])
{
Console.WriteLine("{0} has changed", t.FullName);
break;
}
}
}
else
{
File.WriteAllBytes(fileName, hash);
Console.WriteLine("{0} is new", t.FullName);
}
}
}
File.Delete("temp.txt");
Console.ReadKey();
}
}

Of course, this will only tell you whether the name of a public class or one of its public properties or their types has changed. It won't tell you whether the code or anything else has changed.

Feedback