Click here to Skip to main content
Click here to Skip to main content
Go to top

FileHasher

, 29 Sep 2005
Rate this:
Please Sign up or sign in to vote.
FileHasher is a tool to hash files recursively across a selected folder.

Introduction

FileHasher is a tool to hash files recursively across a selected folder. This is my first attempt to write a useful tool in C# apart from the initial "Hello Worlds". It uses the SHA512Managed class to derive the hash from a file's open stream.

The article has example code for:

  • Threading
  • Delegates and Events
  • Hashing

Implementation

The core functionality in this is the GetHashCode(FileInfo file) method which retrieves the hash code for a given file. To retrieve the hash, we need to convert the FileStream into a byte array which is then passed on to the SHA512Managed.ComputeHash method which returns a byte array containing the hash.

try
{
    BinaryReader br  = new BinaryReader(file.OpenRead()) ;

    bHash = mSha512.ComputeHash(br.ReadBytes((int)file.Length)) ;

    br.Close() ;
    sHash = Convert.ToBase64String(bHash) ;

}

This hash is in a non-printable form, so we now encode it using Convert.ToBase64String so that we can show it in the UI and save it into a file. The above method is called off a recursive method which loops through all the sub folders in the user selected folder.

private void Recurse()
{
    try
    {

        DirectoryInfo [] dirs ;
        string sHash ;
        DirectoryInfo dirInfo = new DirectoryInfo(msPathName) ;

        FileInfo [] files ;

        files = dirInfo.GetFiles("*.*") ;

        foreach(FileInfo f in files)
        {
            if(f.FullName != "." || f.FullName != "..")
            {
                sHash = "" ;
                if(mbAddFiles)
                {
                    //Raise Event
                    StatusUpdate(f.FullName) ;
                    sHash = GetHashCode(f) ;
                }
                mlFileCount++ ;
                //Raise Event
                ProgressCallBack(mlFileCount,f.FullName, 
                                       sHash, f.Length);
            }
        }
        dirs = dirInfo.GetDirectories("*.*") ;

        foreach(DirectoryInfo dir in dirs)
        {
            msPathName = dir.FullName ;
            Recurse() ;
        }
    }
    catch(Exception ex)
    {
        throw ex ;
    }
}

This is the point where it becomes interesting. It is really a CPU intensive job to read all the files and then compute the hash for that. If you run this off a UI code directly you will get the job done, but your UI will be un-responsive.

To ensure that the UI is responsive, the recursive method is run off a thread. This way the main thread in the application is free to take care of the UI and the "worker thread" is building the hashes.

mThread = new System.Threading.Thread(new 
  System.Threading.ThreadStart(fileAdder.HashFiles)) ;
// .... //
mThread.Start();

The requirement for a good UI becomes more challenging at this point. We need a UI which is not only responsive but shows real-time data of what the thread is doing. To enable that, we have to implement callbacks so that the UI can be updated. But the problem here is that the UI is on a thread which is different than the "worker thread". Cross thread data exchanges are not straightforward.

For that reason, you will see four delegates declared in FileAdder.cs.

    #region "Delegates"

    public delegate void ProgressCallBackHandler(int lPos, 
                    string sFile,string sHash,double dSize) ;
    public delegate void HashCompleteCallBackHandler() ;
    public delegate void UpdateTreeCallBackHandler(string sFile,string sHash) ;
    public delegate void UpdateStatusCallBackHandler(string sText) ;

    #endregion

These are raised as events in the Recurse method and when the operation is complete.

public event ProgressCallBackHandler ProgressCallBack ;
public event HashCompleteCallBackHandler HashCallBack ;
public event UpdateStatusCallBackHandler StatusUpdate ;

The MainForm, which is the UI class, locks onto these events for notifications. This scenario works fine with textboxes and progress bars.

But for a tree view, we need an extension to this. We need to call the Invoke method to enable the tree view class to update the UI from across thread data.

tvOne.Invoke(new UpdateTreeCallBackHandler(this.UpdateTree), 
                                  new object[]{sFile,sHash}) ;

Since I had a setup for the thread working, I have added other cosmetic features like "Abort", "Pause" ...

Recommended Reads

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

belthurgp

United States United States
fooling around computers during my college days, now into full fledged development in Microsoft Technology in a big company.
 
check out my site for some small programs I have written.
 

Comments and Discussions

 
GeneralRuntime Error PinmemberMember 471152421-Aug-08 7:09 
GeneralU beat me to it PinmemberTrance Junkie29-Sep-05 21:19 
GeneralRe: U beat me to it Pinmemberbelthurgp3-Oct-05 9:37 
GeneralQuestion ... PinmemberPaul Brower29-Sep-05 7:29 
GeneralRe: Question ... PinmemberMark Focas29-Sep-05 14:48 
GeneralRe: Question ... PinmemberPaul Brower30-Sep-05 2:16 
AnswerRe: Question ... Pinmemberbelthurgp3-Oct-05 9:45 
QuestionHow to ... ? PinmemberVertyg029-Sep-05 5:05 
AnswerRe: How to ... ? Pinmemberbelthurgp3-Oct-05 9:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140926.1 | Last Updated 29 Sep 2005
Article Copyright 2005 by belthurgp
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid