Tuesday, July 29, 2008

DotNUTs Framework - DirectoryInfo.GetFiles and DirectoryInfo.GetDirectories Callback / Event

The .NET framework is far from a refined / polished framework. It's nearly everything that I do in the .NET world, I run into a brick wall which eventually leads to writing my own wrapper around Win32.

Recently, I had to write a file searcher which is mainly used to look for files on USB hard drives. Each folder in the drive is made up of several tens of thousands of files and the drive is usually extremely fragmented (we're not talking about your conventional PC hard drive setup here). Using DirectoryInfo.GetFiles has a fatal flaw when it comes to enumerating files in a folder - it does not have a callback to report its progress, which means there's no way to cancel the search.

The Directory.GetFiles method works well for folders with not too many files but my case, enumeration can take up to a few minutes on a USB 1 connection. It doesn't matter if you implement this in the foreground or background thread - either way, your user will be forced to sit through the enumeration without any progress report or means to cancel the enumeration (unless you want to force a thread abort - still, there's no way to report progress).

So, WinAPI to the rescue, yet again. Using FindFirstFile and FindNextFile, we can easily achieve the same thing. The problem, however, is that in C#, you'll need to pinvoke these functions and the painful part is, you'll need to define everything that is simply a header file include away in C++. If that's not enough, you'll then need to verify that your definitions are correct in that it marshals the arguments back and forth properly.

Finally with all that out of the way, I stumbled upon yet another .NET framework bug in my unit test: DirectoryInfo.LastAccessTime LIES! (although I admit I don't need the LastAccessTime of a directory - but a bug's a bug)

Directory: C:\Windows\assembly
Date Accessed, as reported by Windows Explorer: 29/07/2008 2:08 PM
Date Accessed, as reported by WinAPI: 29/07/2008 2:08 PM (29/07/2008 2:08:38 PM)
Date Accessed, as reported by dotNUTs framework (DirectoryInfo.LastAccessTime): 29/07/2008 2:30:08 PM

It's not the LastWriteTime nor the CreationTime - that leads me to think that dotNUTs must have pulled the value out of its arse - which is not surprising given my experience with dotNUTs.

Does anyone else feel that the .NET framework is plagued with bugs? Or am I just a bug-magnet?

Or maybe someone should help Microsoft with their unit tests?

p.s. I'm not the first to coin the word dotNUTs.

1 comment:

Zach Saw said...

Apparently, this discrepancy comes about because the dotNUTs framework uses GetFileAttributesEx rather than FindFirstFile to determine its LastAccessTime.

In any case, GetFileAttributesEx is buggy (GetFileAttributesEx's WIN32_FILE_ATTRIBUTE_DATA from MSDN):

ftLastAccessTime

A FILETIME structure.

For a file, the structure specifies when the file is last read from or written to.

For a directory, the structure specifies when the directory is created.

The same description can be found for FindFirstFile's WIN32_FIND_DATA structure.

So, how come this yields different results?

Note: Tested on WinXP SP2.