Saturday, July 07, 2007

Code Camp SA vs Code Camp Oz

Peter Griffith introducing the next presentation Today I attended the inaugural Code Camp SA, a two day event with presentations about .NET development inspired by the successful Code Camp Oz held in Wagga Wagga over recent years. Not everyone in Adelaide can afford the time and travel costs to spend a weekend in Wagga so it is great that ADNUG, UniSA, and the ACS have sponsored this event.

I was privileged to attend Code Camp Oz (CCOZ) this year and can't help but compare Code Camp SA (CCSA) to it. CCSA is held in a well-equipped lecture theatre at the local university and an excellent array of accomplished speakers have been gathered to present on relevant topics and upcoming technologies.

The sponsors have also arranged for morning and afternoon tea to be provided to attendees and a tasty BBQ lunch too. All this comes at no cost to the attendees. Unfortunately, CCSA missed a few issues that the CCOZ organisers have learned to expect.

Firstly, the University of South Australia's City West campus is not an area I'm familiar with, posted signage would have been very helpful for locating the venue.

Secondly, attendees like to bring notebook PCs to the presentations and most notebook batteries don't last the seven hours of the event. CCOZ supplied a box of power extension cables to allow attendees to switch their notebooks to AC.

Lastly, for an event dedicated to software developers, the wireless Internet connectivity was poorly organised. At a time when my work colleagues, my friends, myself, and even my parents all have high-speed wireless broadband connections at work and home, I expect the university to offer the same.

 Friday, July 06, 2007

Still Recovering

A new HP Compaq 6710b business notebook arrived at work the other day. It was very shiny, had plenty of grunt, and was preloaded with Vista... apparently. Somehow, during the excitement, the notebook was turned on for the first time and then the lid was closed again before Windows had started. We didn't want to go through the initial setup just then, we had more important things to do.

Later, the time finally came to setup the new notebook and install and configure all the usual goodies. Unfortunately, just after the BIOS POST and before Vista started loading, we were greeted with an Vista boot loader error message: "\windows\system32\winload.exe could not be loaded because the application is missing or corrupt". All other options in Windows Boot Manager lead to the same result and no amount rebooting was going to help.

The answer to this problem, as described on the Boot Loader error screen, is to boot from the Windows installation disc. However HP like many OEMs today, do not ship any CDs with the hardware. To get the recovery disc you would normally burn them after setting up Windows for the first time (Catch-22) or order them from HP (takes about three business days).

Next idea: to be able burn the recovery discs after setting up Windows, HP must, like other brand notebooks, have the recovery images on the hard drive in a hidden partition. I downloaded the user guide from the HP website to find out how to use the recovery images on the hard drive. Option 1, run the HDD based recovery tool from the Start Menu (uh...) or Option 2, press F11 while booting to start the recovery tool without Windows. Excellent.

F11, F11, F11, F11,... doesn't work. POST screen lists others but not F11. Googling suggests that the HP boot-time recovery tool is not a BIOS feature but a boot loader on the recovery partition and the active partition is set wrong if F11 doesn't work. Ok, what is the easiest way to change the active partition on a non-booting PC?

We booted from a Windows XP install disc to use the Windows Recovery Console. XP install couldn't detect a hard drive in the notebook and refused to go any further. We created a bootable floppy with a USB floppy drive on an XP machine and copied diskpart.exe to it. Diskpart requires the full Win32 environment to work. We created a bootable Windows ME boot floppy but FDISK is unusable on drives larger than 137GB.

Lastly, we waited for the Ultimate Boot CD to download from a very slow mirror and we got Ranish Partition Manager running on the notebook. Ranish showed the notebook's hard drive correctly as a 160GB drive. It also showed that there was a single 40GB active partition formatted as NTFS and the rest of the drive was unpartitioned. Bugger.

We are now waiting for the recovery discs to arrive in the post from HP. I'm guessing that the guys at HP who setup the initial Vista image for this notebook range forgot to leave the recovery partition intact. Just goes to show though, shut down your PC properly.

 Tuesday, July 03, 2007

Spend More

Ferrari I've always maintained an interest in the current PC hardware scene. I like to keep abreast of the performance, prices, and problems with the various components available. I've built many PCs for myself, my friends, my employer, and even registered a business and sold a few to the public.

Understandably people often ask for my opinion when they are looking to buy a PC for themselves. I'm very very slowly coming to the realisation that I need to stop "helping" these people. Most of the time I have recommended components or systems that I have personally owned but even then their experience isn't necessarily the same as mine and then I feel responsible when it doesn't work out.

I have stopped operating my personal business and now I pay retail for all my hardware instead of going to wholesalers. I have also stopped building my own PCs and my last three purchases have been big name, off the shelf computers. It just isn't worth my time anymore to save a few bucks wherever I can.

From now on, my advice to myself, and to anyone else who asks, is to spend more. Looking for a new computer, LCD monitor, or video card? Spend more. Not everyone can afford it, it's not going to give you the best grunt for your money, but it sure has saved me a lot of time messing around. It's also a lot more affordable than buying the cheap option only to discover it sucks and you need to buy the expensive model too.

 Monday, July 02, 2007

Dreams and Mistakes

Firstly, in my recent post about the new .Net DateTimeOffset class I mentioned that I would love to see the SQL Server team include this type in databases. My wishes have been answered, we can expect to see this type and some other very interesting additions in the next CTP/Beta of SQL Server 2008. Unfortunately, all of our clients have bought into SQL Server 2005 and won't be interested in upgrading anytime soon so I'll have to find a new project to try all the new toys.

Secondly, also in a recent post I complained about the CollectionBase type being left behind when generics were added to .NET 2.0. I've since discovered the new Collection<T> class tucked away in the System.Collections.ObjectModel namespace. It doesn't offer all the events that the previous equivalent did but it is inheritable and overridable so it should do the job nicely. I obviously didn't search very hard for it all the other times I looked; very embarrassing.

Death, Taxes and Software

Tax Calculator The new 2007/2008 financial year has begun and as promised the Australian Taxation Office released the latest version of their e-tax software on July 1st. As I have for the past several years, I downloaded and installed the software and have started entering my income and deductions for the last 12 months.

When the official paperwork arrives, I'll confirm all my figures and submit my tax return electronically and receive my rebate usually within a week, deposited directly to my bank account. Considering the complexity of the income tax system, the software is excellent for non-accountant-types to complete their own tax return.

Unfortunately, e-tax 2007 is still stuck in the obsolete Windows administrator user world. Installation defaults to "c:\etax2007\". It has been over twelve years since Windows 95 was released and the standard was set for software to install into Program Files.

A single e-tax installation on a PC allows multiple people to fill in and submit their tax return, saving their work in progress locally until it is ready to send. However, the software assumes the user is an administrator and writes the *.tax progress file to the installation folder instead of Documents & Settings.

At several stages throughout the questionnaire, summaries and important details are presented to the user with a recommendation to print the information. However, the software always uses the default printer with the default settings, offering no dialogs, and only picking up changes to the default printer after restarting the software.

One of the biggest reasons why e-tax is so great is because the questions are presented in easy to understand language. Whenever more detail is required there are always hyperlinked keywords or a help button leading to a more extension definition with examples. Sadly, it's all useless under Vista because they've stayed with the deprecated WinHelp format for the documentation.

Lastly, for users of Apple computers (and presumably other OSes), the official solution is to use virtualization. I wonder if the purchase price of VMWare or Parallels and a Windows licence can be claimed as a cost of preparing the tax return.

By all appearances e-tax is a full Win32 application, probably written in C++ at first glance, and is expected to continue in that style for the majority of users next financial year too. Perhaps by 2009, they will have moved to a web-based client, which will open the system to non-Windows users but probably introduce other problems along the way.

 Wednesday, June 27, 2007

Ecstatic About NStatic

Ecstatic MascotWesner Moise is getting ever closer to public release of his very promising NStatic static analysis tool for .NET. In general static analysis tools are very expensive but as part of Wes' plans, a lower price to achieve market penetration is most likely. In fact, until he finds a suitable publisher he expects to selling independently for a few months, during which time we might be lucky to pick it up for a "bargain" price.

So far I think NStatic only supports C# 2.0 but there are plans to add support for C# 3.0 features and maybe VB.NET too if the demand is there. I, for one, sure hope that VB support becomes a reality, I think our current suite of software could really benefit from some in depth analysis.

Keep a close eye on Wesner's blog for the latest information.

DasBlog Flip Flop

A few months ago I upgraded this web site from the DasBlog 1.8 installed by my ISP to the latest version at the time, 1.9.6. It was remarkably easy to merge my web.config and site.config files and upload all the new binaries.

Yesterday Scott Hanselman announced DasBlog 1.9.7 had been released. Last night I tried to upgrade again, following a very similar procedure as I did the last time. Being a point release, I expected even less effort and was happy to find that very little merging was required with the config files.

Unfortunately, once I had uploaded the new files to my site I found I could no longer log in. I refreshed the browser several times, edited and uploaded the siteSecurity.config file several times and tried the default file with the admin/admin credentials. Nothing would let me login and all I had was a SecurityFailure message in the event log.

This took an hour or so and I eventually gave up and completely restored the backup I made before attempting the upgrade. Guess I'll have to configure IIS locally and experiment until it works.

On a better note, Scott says this is the final release for ASP.NET 1.1 and another release due very soon will be completely ASP.NET 2.0 and support Medium Trust. I was annoyed last time I downloaded the source and discovered that I would need to install VS2003 to work with it but finally I'll be able to contribute to the project.

 Tuesday, June 26, 2007

DateTimeOffset Is The New DateTime

SundialJustin Van Patten neatly summarises the new DateTimeOffset class introduced in .NET 3.5. In short, this new class combines the year, month, blah, blah, second storage of the DateTime with a time zone offset. The most important point to take from Justin's article is that apart from a few exceptions (which he describes), you should always use DateTimeOffset in new code instead of the old DateTime.

Naturally there will continue to be situations where you need to pass a DateTime but the DateTimeOffset will always be able to scale back to suit. It is much harder to infer time zone information from a DateTime to provide a DateTimeOffset. I'd love to see the SQL Server team introduce this data type concept to databases.

CollectionBase and Generics

In .NET 1.1 the Framework included an abstract class System.Collections.CollectionBase. The idea was that you could extend it to create your own custom collections to hold certain types. The Add, Remove, and other methods were overridable (to perform object validation or filter duplicates) and several events also existed to enable listening for changes.

Cardboard Box Most importantly it provided the mind-numbing mapping from the IList, ICollection and IEnumerable interfaces to the internal storage mechanism (which happened to be an ArrayList). When I created a new collection derived from CollectionBase I could override the OnValidate method to only accept a certain type and I was done.

Sadly, I'm left stranded in my .NET 2.0 world with Generics and an untyped CollectionBase. I cannot inherit from List<T> because none of it's methods are virtual and none of it's fields are protected. Ultimately, I'm stuck with writing my own class with a private List<T> field and coding most of the methods on the various interfaces as redirections to the private field. No thanks, that was one of the biggest reasons for moving from VB6 to .NET.

Interestingly, the SharePoint fellows noticed the same problem with CollectionBase's obsolescence in .NET 2.0, and cleverly decided to provide the more up-to-date CollectionBase<T>. Of course, not only did it end up in the Microsoft.SharePoint.Publishing assembly that I'm reluctant to reference and probably unable to distribute, but they also implemented only ICollection and IEnumerable<T>. I was dumbfounded that IList<T> and ICollection<T> had been missed and that they had also removed IList.

Why am I still forced to code this junk myself?

Windows Vista, UAC, Flame On!

If you are running Windows Vista and are bothered by "too many" UAC dialogs on a regular basis to the point that you want to turn UAC off, the problem is that you are futzing with your PC instead of doing real work.

 Saturday, June 23, 2007

Crashing Visual Studio Unit Testing

Yesterday I managed to crash vstesthost.exe, the program that runs Visual Studio Unit Tests when you press Ctrl+Shift+X. A few tests in my suite would run and pass, then BAM, fatal error. I ran the tests again, this time in debug mode and the tests broke into the debugger with a StackOverflowException, due to a poorly implemented interface in a mock object.

According to some searching, some exceptions including StackOverflowException, just cannot be caught in .NET 2.0 and I'm not sure it would be smart to try. Unfortunately when it happens in testing, the whole suite fails. In my case, I was able to pave over my mistake in the code and move on with my life.

The vstesthost crashing problem also happens when an exception is through on a secondary thread though. Testing asynchronous UI or background processing code could also kill the process when any exceptions occur, and these might be expected exceptions for a particular tests.

I haven't needed to use it yet, but there is a workaround to avoid the whole test suite falling over. It involves editing the vstesthost.exe.config file to enable the legacy unhandled exception policy as used by the earlier CLR versions. You will need to be careful to synchronise your threads though to ensure any exceptions are assigned to the correct test in the results.

 Friday, June 22, 2007

Feature Suggestion For DotNetKicks

DonkeyGavin Joyce announced a few months ago that the DotNetKicks community website will be going open source. Gavin has since created a DotNetKicks project on Google Code with some placeholders and has asked for people interested in contributing to join. One thing that isn't clear is whether the engine will be open source for others to build their own sites or if all the updates will get deployed back to DotNetKicks.com.

Regardless, I already have one idea in mind. In a moment of complete clumsiness, while trying to quickly submit a post to DotNetKicks before going to bed, I associated the wrong Title and Description with the wrong Url. Unfortunately, even though I had submitted the item, I was unable to correct the Title or Description and I was unable to delete the submission altogether and start again. I unkicked the post back to zero kicks but that didn't help.

My suggestion therefore, is that the submitter of an article should be able to delete that submission. Perhaps, to be safe, it could be restricted to only allow deletion if no one else has kicked it.

Until then, I'll just have to live with looking stupid for my story on DotNetKicks which, strangely, someone other than me has kicked anyway.

Drive By PowerShelling

I have been using an external USB hard drive to take backup copies of certain files on several machines. Each machine has different drive configurations though so the USB drive will be assigned different drive letters on each machine.

I could have found an unused drive letter common to all the machines and assign it to USB drive on the first use but that's no fun. I decided to do it the PowerShell way. I wrote a small function to find a System.IO.DriveInfo object by providing the volume label and then I can get the drive letter and pass it to Copy-Item to do the work.

function Get-DriveInfo ([string] $label = $(throw "Please specify a volume label.")) { 
   [System.IO.DriveInfo]::GetDrives() | ? { $_.IsReady -eq $True -and $_.VolumeLabel -match $label }
}

 Wednesday, June 20, 2007

Beware The Evil Shadow

Evil Shadow Object-oriented programming principles have been an excellent addition to software development but one component that inevitably appears in OO languages has confounded me by it's uselessness. In VB.NET it is known as the "Shadows" modifier, in C# it is found in class member declarations sharing the name "new".

The purpose of this modifier keyword is to allow a subclass to redefine a property, field, or method of the base class where the base class has not been declared "Overridable" or "virtual" in VB.NET or C# respectively. Unfortunately it suffers from a major drawback, as demonstrated by the following code:

class Base
{
   virtual public string Extendable() { return "Extend"; }
   public string Locked() { return "Lock"; }
}

class Foo : Base
{
   override public string Extendable() { return "Food"; }
   new public string Locked() { return "Picked"; }
}

Base b = new Base();
b.Extendable(); // returns "Extend"
b.Locked(); // returns "Lock"

Foo f = new Foo();
f.Extendable(); // returns "Food"
f.Locked(); // returns "Picked"

Base bf = new Foo();
bf.Extendable(); // returns "Food"
bf.Locked(); // returns "Lock" !!!

As you can see, if the Foo methods are called via a Foo-typed variable, there is no difference between shadowing and overriding. However, as soon as you call a Foo method via a Base-typed variable, or pass a Foo instance to another class expecting a Base, you lose the functionality of Foo.

If "new" is omitted from Foo's implementation of Locked, Visual Studio reports an error: The keyword 'new' is required on 'Locked' because it hides method 'Base.Locked()'. It is very easy for someone to simply add the keyword as required with realising the consequences.

Occasionally, all you might want to do is utilise some existing behaviour in a base class and add some more features and shadowing or member hiding is fine. The fact that you have used shadowing is not obvious in the calling code though.

Most of the time, I want to alter the behaviour of a base class and pass my new subclass to existing code, perhaps in the Framework, that is only expecting the base type. Beware.

Waste Management

The script in my last post for removing old files from the temporary folder is only necessary because so many applications don't clean up after themselves. Hopefully, if the applications you are developing are doing the right thing they will be using in memory streams where ever possible. Only write to disk when absolutely necessary, creating random temporary files in the environment temp folder, not program folders with restricted access to non-admin users:

string myTempFile = System.IO.Path.GetTempFileName();

However, remembering to track and delete these files when you are finished requires more effort and is often ignored, creating the ever growing temp folder problem. There is a lesser known class in the framework that can help you though:

var myTempColl = new System.CodeDom.Compiler.TempFileCollection();
string myTempImageFile = myTempColl.AddExtension("png");

Excuse the C# 3.0 syntax in the last snippet, I hate the redundancy of repeating long type names, especially on the same line. When you have finished using all the temp files you created with the TempFileCollection, you can dispose it explicitly, automatically deleting the files, or if you're really lazy, let the GC take care of it.

myTempColl.Dispose();

PowerCleaning

I've often wanted to easily delete all old files below a folder that haven't been modified for a while. I've written a very small PowerShell function to do just that. By default it emulates the Disk Cleanup tool in Windows and deletes all files older than one week from the environment temp folder.

function Remove-TemporaryItems ([string] $path = ($env:TEMP), [TimeSpan] $age = (New-Object System.TimeSpan 7, 0, 0, 0) ) {
    $files = Get-ChildItem $env:TEMP -recurse | `
        Where-Object { ! $_.PSIsContainer -and $_.LastWriteTime.Add($age) -le [DateTime]::Now };
    $files | Remove-Item;
    $files;
}