Monday, January 28, 2013

File used by another process - how to check

During my recent debugging, I got the following error when I try to open a file using System.IO.FileStream.

The process cannot access the file 'D:\dev\store.db.file' because it is being used by another process.
The thing is that it was obvious that no other process used the file at the time. Simplified version of the code looks like this.
public void SynchronizeData()
{
    XDrive dr = new XDrive(token);
    var statusCode = dr.Download("store.db");
    if (IsValid(statusCode))
    {
        this.MergeData();
    }

    this.CopyFile();
    //....

    dr.UploadDbFile("store.db");
}
I wanted to know which process or which part of my application was using the file. I set breakpoint at the begining of the method and went step by step. While steping over line by line, I ran Process Explorer from sysinternals and opened [Process Explorer Search] by using [Find] - [Find handle or DLL] menu (or Ctrl - F as a shortcut). In a search box, I put a filename - store.db.file in my case.



In every step I investigated whether the file was used and it turned out one of my function did not close file handle. In my case, MergeData() method used the file but did not close it. (well, I did not call Dispose() method for SQLite data adapter)
private void MergeData()
{
    //..... cut ....
    string connStr = "Data Source=store.db.file";
    using (SQLiteConnection cn = new SQLiteConnection(connStr))
    {
        SQLiteDataAdapter adpt = new SQLiteDataAdapter(sql, cn);
        adpt.MissingSchemaAction = MissingSchemaAction.AddWithKey;
        adpt.Fill(dsDown);
        //adpt.Dispose();
    }            

    //..... cut ....
}

So Process Explorer can be useful when trying to figure out which process (or which part of the functions) holds a handle or owns a DLL.
By the way, the error message "because it is being used by another process" is kind of misleading since in my case, it was not other process, it was its own process.