tags:

views:

1489

answers:

7

Edit: I've retitled this to an example as the code works as expected.

I am trying to copy a file, get a MD5 hash, then delete the copy. I am doing this to avoid process locks on the original file, which another app writes to. However, I am getting a lock on the file I've copied.

File.Copy(pathSrc, pathDest, true);

String md5Result;
StringBuilder sb = new StringBuilder();
MD5 md5Hasher = MD5.Create();

using (FileStream fs = File.OpenRead(pathDest))
{
    foreach(Byte b in md5Hasher.ComputeHash(fs))
        sb.Append(b.ToString("x2").ToLower());
}

md5Result = sb.ToString();

File.Delete(pathDest);

I am then getting a 'process cannot access the file' exception on File.Delete()'.

I would expect that with the using statement, the filestream would be closed nicely. I have also tried declaring the filestream separately, removing using, and putting fs.Close() and fs.Dispose() after the read.

After this, I commented out the actually md5 computation, and the code excutes, with the file being deleted, so it looks like it's something to do with ComputeHash(fs).

+1  A: 

Did you try wrapping your MD5 object in a using() too? From the docs, MD5 is Disposable. That might make it let go of the file.

Moose
Yeah, you probably want to abstract a function that takes a filename and returns a hash string.
Mark
A: 

Have you tried setting md5Hasher to null before deleting the file? It probably has a handle still attached to the FileStream (memory leak perhaps).

Jagd
A: 

Don't you need to close the file before you deledt it?

JonnyBoats
Why the down vote?
JonnyBoats
A: 

Why not open the file with FileShare.ReadWrite?

Factor Mystic
A: 

md5hasher.Clear() after your loop might do the trick.

JP Alioto
+4  A: 

I took your code put it in a console app and ran it with no errors, got the hash and the test file is deleted at the end of execution? I just used the .pdb from my test app as the file.

What version of .NET are you running?

I am putting the code that I have that works here, and if you put this in a console app in VS2008 .NET 3.5 sp1 it runs with no errors (at least for me).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace lockTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string hash = GetHash("lockTest.pdb");

            Console.WriteLine("Hash: {0}", hash);

            Console.ReadKey();
        }

        public static string GetHash(string pathSrc)
        {
            string pathDest = "copy_" + pathSrc;

            File.Copy(pathSrc, pathDest, true);

            String md5Result;
            StringBuilder sb = new StringBuilder();
            MD5 md5Hasher = MD5.Create();

            using (FileStream fs = File.OpenRead(pathDest))
            {
                foreach (Byte b in md5Hasher.ComputeHash(fs))
                    sb.Append(b.ToString("x2").ToLower());
            }

            md5Result = sb.ToString();

            File.Delete(pathDest);

            return md5Result;
        }
    }
}
Brian ONeil
The code does work, I am a n00b. I was reusing the file after the MD5hash which was locking the file.
mattdwen
A: 

MD5 Checksum for a file can be used when validating an important file copy downloaded from the internet. Comparing the original checksum with the destination checksum returned from the code sample below to verify if the file is valid.

http://w3mentor.com/learn/asp-dot-net-c-sharp/c-file-handling/calculate-md5-checksum-for-a-file-in-c-csharp/