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.

Sunday, July 13, 2008

Borland / CodeGear Delphi / C++ Builder

It's sad really to finally see Borland closing a chapter on its very successful product - the VCL.
VCL has been the foundation of the .NET framework Windows Forms portion and in many ways still does a much better job - such as subclassing common controls, wrapping it into a 'drag-drop'-able control. Amazingly, Borland's core controls in the VCL has remained mainly unchanged since Version 5. With a few tweaks and additions to make it use Vista theme, it was made theme-aware in Vista.
What can we say about the .NET framework then? Well, as of Orcas (VS 2008 for the less informed), most controls are still not Vista themed - and most of the controls are around about VCL's version 3 standards in terms of features, bugs, and extensibility (ease of derivation, subclassing etc.).
Yeah yeah, there's WPF, but heck, some controls in WPF are even worse than their Windows Forms counterparts. And, using WPF simply means shooting yourself in the foot when it comes to finding the lowest common denominator - heck, I can't even run WPF apps at a decent speed on my 3 year-old laptop.
Microsoft's solutions - WPF or Windows Forms - are very half-hearted. They are neither very usable, or completely unusable. Most of the time, you'll have to invest a lot of your own time and resources into making something useful out of it.
Just for example, the TreeView control - both Borland (CodeGear) and Microsoft have it. Which is better? Borland (CodeGear) hands down (I expect Borland fan boys to cheer and Microsoft fan boys to boo now -- Darn those people - get a life!).
I worked with a guy with MCSE creditation last year (typical Microsoft fan-boy) and was told that anything I could do with Borland (CodeGear), I could do with Visual Studio / .NET framework. Sure. Try creating a multiselect TreeView that works in both Vista and XP, natively themed (i.e. Vista explorer mode theme and in XP, fall back to the active XP theme). In Borland (CodeGear), you'd simply drag-n-drop and set the multiselect property to true. Zero lines of code. I dare you - you know who you are, you Microsoft fan-boy - try doing that in Visual Studio and see how long it would take you to do something similar.
Yeah, sure, I did it eventually - check out my Advanced TreeView Control here - but it took me some time. And sure, the fan-boy could've simply said, well, I told ya, it could be done. And my reply would have been, "Yeah, it could've also been done in pure ASM!"
Good on ya Microsoft!

Thursday, July 10, 2008

The Online Vultures

I think I'm going to coin a new term here - The Online Vultures.

There are quite a few companies out there waiting for a domain, particularly a very highly ranked domain (in search engines) to

expire, and if the owner does not renew it, these companies pound on the domains, analogous to vultures ripping apart a dead

carcus. If you even try to get the domain back, you'll face the wrath of these vultures pecking you to death! Not that you should

let your domain expire, but that's a tale for another day.

How do these companies get money off sites like these?

Simple. They park a website on the expired domain, with a link oh-so-visible to "Enquire about the Domain". Following the link,

you'll be presented with a form which asks you for your contact details and the most important question of all, "How much are you

willing to pay for the domain?" (all these are provided by Domain Parking service).

Companies like the following is an example:

created-date: 2007-05-04 18:16:31
updated-date: 2007-09-06 13:48:52
registration-expiration-date: 2009-05-04 00:00:00

owner-contact: WA-VirtualStockLtd
owner-organization: Virtual Stock House LTD
owner-fname: Andrew
owner-lname: Waggins
owner-street: Midtown Building, 625, D.R. Walwyn Square
owner-city: Charlestown
owner-zip: 001
owner-country: SAINT KITTS AND NEVIS
owner-phone: +18696124652805
owner-fax: +18696124652805
owner-email: vsh.ltd@googlemail.com

This 'company' (whether or not it's real) owns 3,557 other domains.

Try www.micrusoft.com and www.micrasoft.com, or even www.iApple.com - they are all domain parked. Amazing.

Tuesday, July 8, 2008

Application Data - The WinForms Cookies

The application data folder (%USERPROFILE%\Local Settings\Application Data) is guaranteed to be read-writable and furthermore, it is user specific. Compounded by the ease of use via the IsolatedStorage class in the .NET framework, this sounds like the ideal place to save all your user settings doesn't it?

It is. Just an example, Microsoft Visual Studio caches all your project assemblies there. If Microsoft does it, it has to be correct, right? Yes and no.

While this is one of the most convenient storage locations, there is, however, the issue of - when and how do we remove the data we have stored in app data folder?

Microsoft Visual Studio suffers from this exact problem with its project assemblies - it really shouldn't, but it does. And when that happens, it will drive you nuts. What am I talking about? Here goes.

When a solution is loaded, all the referenced assemblies which have their property "Copy Local" enabled will be cached in %USERPROFILE%\Local Settings\Application Data\Microsoft\VisualStudio\\ProjectAssemblies\. The next time you open the solution, Visual Studio will check the cache for the assemblies and will not recopy the assemblies even if they are out of date. This happens very frequently if you use any third party components / controls with designer support - every time you upgrade to a newer version, your solution breaks as you now have an older version of the assembly in your cache, while the designer expects to work with the version it gets installed with.

The problem arises simply because Visual Studio does not remove the cache when the user closes the solution. It really should not retain the cached assemblies simply because these files will then remain indefinitely in your application data. Imagine every single time you create a little application to test out the behavior of certain components / controls (be it built-in or third party), VS caches all the assemblies. If Microsoft insist on not deleting the files, at least have the courtesy of doing it properly - this is analogous to Intel's Nehalem processor (the successor of Core processor) using stale data from its L3 cache!

In the case of VS, the solution is simple - recopy the assemblies each time the solution is reloaded.

Users of IsolatedStorage though, have a bit more problem in that if we use IsolatedStorage for application settings, when do we clean it up? When the software is uninstalled? Seems like quite a hassle - in the uninstaller, figure out which subfolder is for the application we have installed, enumerate through all the user profiles and delete the data files.

OK. Before we go any further, how do we figure out the subfolder of which our application has used for IsolatedStorage? Is this relative location even the same for all the users? Where's the documentation for this?

Too much hassle means one thing - most developers / companies will simply leave the files in IsolatedStorage after the application gets uninstalled. I suppose that's a bit better than leaving the data in your Windows registry back in the old days.