Monday, August 27, 2007

Convert DVD to iPod

I have just spend two weeks on holiday and before I left I wanted to transfer some of my DVDs to my iPod Video to keep my fiancee and I entertained whilst traveling to our destination. Unfortunately I didn't really think about this soon enough and didn't have time to get it organised. Now that I'm back home though I've been able to look into it further.

The biggest problem I found with converting DVDs to an iPod suitable format is that the movie studios don't seem to want to allow it. This results in either a complicated list of steps involving multiple tricky applications or purchasing an all-on-one solution from a questionable overseas company. Luckily though, Hanselman recently updated his Tools List for Windows, which included a link to Videora Converters, a suite of video transcoding programs available for free. If Hanselman recommends it and I don't have to provide payment details, it's worth a try.

I downloaded their iPod converter and started following their slightly outdated guide for converting DVDs. I grabbed my Futurama box set and put the first disc in. The first stage involves using the getting-harder-to-find DVD Decrypter to rip and decrypt the appropriate video and audio stream without all the extra DVD menu junk. Thankfully I'm familiar with DVD Decrypter and even more so that it works fine as non-admin in Vista 64-bit.

The second stage involves installing and running the Videora software, selecting the file that DVD Decrypter produced and waiting for it to convert the MPEG-2 data to Apple's particular MPEG-4 format. This took less than 10 minutes on my Core 2 Duo to convert a 22-minute animated episode into a 137MB MP4 file. When complete, the video played well in the PC QuickTime player and after using iTunes to transfer it to my iPod it played great there too.

Sadly, while the Videora software is free and written in .NET too, it suffers from two major problems. Firstly, it is so filled with advertising in the program itself that it's hard to see where to start and I began to wonder if I'd just voluntarily installed malware. Secondly, the software is designed to run as an Administrator, trying to write configuration data to Program Files, and under Vista, even as an admin, it crashes hard on exit.

Ultimately, if you want some favourite DVD movies or episodes on your iPod, this is probably the easiest way.

 Wednesday, August 22, 2007

Faster User Switching

I run several Vista machines each with several user accounts. Sometimes the different accounts are for different people, sometimes they are for different purposes with different permissions (ie development vs testing). Windows XP introduced a featured called "Fast User Switching" that allowed you to log into another user account without logging off the current session and Vista improves on this by allowing it in domain environments too.

But it's not enough. I want it to be faster. At the moment, in Vista, it takes far too many key presses or mouse clicks to switch to another user. This is the quickest method I've discovered so far:

Ctrl+Alt+Del, Alt+W, select account, enter password, Enter.

However, I recently discovered a much faster approach. I bought a new laptop with Vista and a built-in Vista-driver-compatible fingerprint reader. Now I've associated different fingers with different accounts and at any time I can just slide the appropriate finger over the reader and *bam*, I'm logged into another account.

Still, if anyone knows, a better keyboard shortcut would be great for the PCs without fingerprint readers.

 Thursday, August 02, 2007

PowerShell Registry Find and Replace

Keys I recently encountered a server where SQL Server had somehow been installed to the admin user's mapped U: drive instead of drive C:. As a result all SQL file paths in the registry referred to "U:\Program Files\Microsoft SQL Server\..." but for most users (including the SQL service account) the U: drive did not map to C:. This prevented Management Studio from working and probably many other issues that weren't as visible.

I wanted a fast way to find all "U:\Program Files" references in the registry and repoint them to drive C:. The standard Windows regedit.exe only supports Find but not Replace (and there were a lot of keys to fix) and third party registry tools available on the Internet fall into the untrustworthy category for fixing servers.

I ended up writing a quick C# console app to perform the job.The C# app was able to solve the problem and the server works properly now but I felt there should be an easier way: PowerShell.

I've spent an evening hammering out a basic pair of find and replace functions for PowerShell. They don't make as much use of PowerShell's declarative pipelined nature as I'd like but they work well. The replace function is particular dangerous if you misuse it so be careful. Perhaps I will implement the -WhatIf switch some day.

The find function is simply named Find-RegistryValue. At the moment the function only looks in values, not keys or value names because these are already quite easy to search on with basic PowerShell one-liners. As input the function expects a "seek" parameter being the text sought and optionally a path to a registry key to begin searching from. If the "regpath" is not provided it defaults to Get-Location and if it is not a registry path it throws.

The find function will return an array of Hashtable objects with all the information you should require: the RegistryKey, the name of the value in the key, and the value itself containing the sought text. The code follows:

function Find-RegistryValue (
    [string] $seek = $(throw "seek required."),
    [System.Management.Automation.PathInfo] $regpath = (Get-Location) ) {

    if ($regpath.Provider.Name -ne "Registry") { throw "regpath required." }

    $keys = @(Get-Item $regpath -ErrorAction SilentlyContinue) `
        + @(Get-ChildItem -recurse $regpath -ErrorAction SilentlyContinue);

    $results = @();

    foreach ($key in $keys) {
        foreach ($vname in $key.GetValueNames()) {
            $val = $key.GetValue($vname);
            if ($val -match $seek) {
                $r = @{};
                $r.Key = $key;
                $r.ValueName = $vname;
                $r.Value = $val;
                $results += $r;
            }
        }
    }

    $results;
}

The replace function is named Replace-RegistryValue and relies on the find function to work, resulting in very similar behaviour. It requires the text sought and the registry path just like the find function but it also requires the "swap" parameter which is the text to replace the sought value with. It calls the find function itself and uses the output to first promote the key to a writable instance then replace the value and return the results. The results include the RegistryKey, the name of the value in the key, the old value and also the new value. Here is the code:

function Replace-RegistryValue (
    [string] $seek = $(throw "seek required."),
    [string] $swap = $(throw "swap required."),
    [System.Management.Automation.PathInfo] $regpath = (Get-Location) ) {

    $find = Find-RegistryValue -seek $seek -regpath $regpath;
    $results = @();

    foreach ($target in $find) {
        $nval = $target.Value -replace $seek, $swap;
        $r = @{};
        $r.Key = $target.Key;
        $r.ValueName = $target.ValueName;
        $r.OldValue = $target.Value;
        $r.NewValue = $nval;
        $results += $r;
        $wKey = (Get-Item $r.Key.PSParentPath).OpenSubKey($r.Key.PSChildName, "True");
        $wKey.SetValue($target.ValueName, $nval);
    }

    $results;
}

If you have any suggestions for improving the code or perhaps even a better naming convention for the pair, please leave a comment.

 Tuesday, July 31, 2007

My iPod In My Car

Not my car About twelve months ago I bought a new car and installed some basic necessities: alarm, central locking, and a better-than-factory stereo. For the stereo I picked up the now superceded Pioneer DEH-P4850MP "CD Tuner". I chose this model because it had good features for the price bracket and Pioneer seemed to have the best iPod support at the time.

Pioneer's iPod integration came in the form of the CD-IB100 II interface adaptor, a small module with the iPod dock connector on one end of cable and the Pioneer proprietary P-Bus connector found on most Pioneer car stereos. With a quick specialist installation, I had my iPod 30GB Video ready to crank.

For playing the music collection on my ipod through the car speaker system the Pioneer setup is great. For seeing and controlling what I'm listening too, there is definitely room for improvement.

The head unit has a 16-character alphanumerical display that scrolls artist and title information from audio discs with CD-TEXT. The iPod has full ID3v2 artist, album, title and all sorts of other information for each song. Combined the Pioneer equipments works together with the iPod to present the first eight characters only. I have it set to show artist because eight letters of a song title are quite useless but William Hung, William Orbit, and William Shatner are indistinguishable on the display.

The head unit also allows (forces) you to navigate the songs on your iPod via the stereo controls or the stereo's remote. You can navigate by artist, album, song, genre and even iTunes play list but after every press of the next or previous button, there is a delay while the iPod seeks to the first song in your selection and starts playing it. When you're listening to Bruce Dickinson and want to switch to Nick Cave it is very painful waiting for each of the artists in between to start playing before you can push the skip button again. The Pioneer iPod adapter is a great example of electronic hardware engineers developing end-user software.

Thankfully, while the iPod's built in controls are disabled when connected to the stereo it is really easy to disconnect it to queue songs the normal way or to take the iPod with you when you leave the car. The iPod also does a great job of remembering the current position in the current song when you turn the car off or disconnect the iPod.

Ultimately I'm happy with the system and have created five basic mood-oriented random play lists to minimise navigation pain. My fiancee isn't as happy though as most of the music is mine and while I like to listen to some more obscure stuff, she prefers mainstream songs.

ArgumentNullException: No Message Required

I have been encountering code recently that bugs me. Many methods in classes are testing their arguments for null/Nothing and, if true, throwing a new ArgumentNullException. So far, all good. However, the constructor for the new ArgumentNullException is being passed both the name of the argument and also a message string of the form "_paramName_ cannot be null".

This is totally redundant. The exception being thrown is an Argument *Null* Exception. That about sums it up. Also, if the constructor is passed the parameter name only the message defaults to "Value cannot be null".

Providing a message for an ArgumentNullException requires extra typing, requires maintaining the argument name in three places if it gets renames, and violates FxCop rule CA1303.

Thankfully it turns out it isn't fellow team members doing it. Developer Express' Refactor Pro has a "Create Method Contract" refactoring that is putting the message in.

Visual Studio 2008 Beta 2

I installed VS2008 Beta 2 on a spare machine on the weekend and I am beginning to use it for development. Today I waded through the Tools, Options dialog setting up the IDE with a few sensible defaults. Several default values have changed since VS2005 and for the better. Unfortunately two settings are still outdated.

VB still defaults Option Strict to Off whilst Option Explicit and the new Option Infer are On. They should all be on by default.

Also, when the new range of Microsoft fonts were released for Vista and Office, an update for VS2005 was released to use the new Consolas type in the IDE. VS2008 still defaults to the non-ClearType Courier New though.

Aside from those two issues so far, I'm loving the new Visual Studio.

 Monday, July 30, 2007

Serialization Engine Wish List

Cereal On several occasions I have need to serialize an object graph in memory out to a stream and also needed to read XML data back into objects. Each time I'm confronted by such a task I find myself hunting through the various MSDN serialization topics and becoming increasingly depressed.

Neither the System.Runtime.Serialization namespace nor the System.Xml.Serialization namespace seem to fit my requirements without needing to write large chunks of custom serialization code. It's getting to the point that I'm tempted to write my own serialization engine.

I know that if I do write my own engine, it will consume most of my time, so for now I'm simply going to document what I'd like to see in said engine.

  • Classes should not require a parameter-less constructor to be deserialized. As a simple alternative a class could define a static method which takes a collection of key value pairs from the engine, creates an instance via an appropriate constructor and returns it back to the engine. Ideally the engine would support declarative attributes on an existing constructor defining how to call it.
  • Classes should not need to override their entire serialization process because the engine does not understand one of it's field types. If my class has four integer fields, two string fields, and a complex unserializable Foo field, the engine should handle the integers and strings itself then hand the final stage to my custom serialization function to handle only the Foo field.
  • Classes should be able to override part of the serialization process then return control to the engine to finish the task. Extending my Foo example, I might have custom code to step in and serialize the Foo data but if Foo has a simple serializable member of type Bar, I want to hand serialization of that member back to the engine.
  • Classes should not need public modifiers on members to enable serialization. The engine should make efficient use of reflection to access private and protected members. Ideally the CLR would have a serialization-access level to allow an engine to work with private members in a low trust environment. I think serialization is such a fundamental function that it warrants some cooperation and special treatment by the runtime environment.
  • Classes shouldn't care what format the engine is serializing to or from. If it's binary, SOAP, XML, JSON, or any other new format, the attributes on my class and my custom serialization code should not need to change.

I'm sure there are some other requirements that I've forgotten and I'm sure this is somewhat too late for Visual Studio 2008 but hopefully I'm not the only one that feels this could be improved. What challenges have you faced with the .NET serialization system?

 Saturday, July 28, 2007

Visual Studio versus MSBuild

Hammer I have recently setup a TFS Team Build server for our work projects after realising that the secondary reference issue is not as problematic as first thought. We haven't been using Visual Studio's Remove Unused Reference feature as much as expected and we need to prepare our projects for Visual Studio 2008.

With a build server configured to perform automatic builds every night we are on our way to full continuous integration with builds on check-in. However, there are several other differences between Visual Studio and MSBuild that are creating slight issues for our TFS build agent.

For what I understand of the situation, Visual Studio utilises an in-process variation of the MSBuild engine to support specific features like background compilation but has failed to maintain full compatibility.

For example, installation of SQL Server 2005 on your development machine will offer four new Business Intelligence project types: Analysis Services, Integration Services, Report Server, and Report Model. None of these project types will build from the command line in MSBuild or therefore Team Build. We have had to move these project into separate solutions that we exclude from the build server's automated processing.

Also, strongly-typed DataSets and other designer-based project items are usually based on a metadata file (like an XSD) and use a custom tool to generate an appropriate VB or C# code file before the project is compiled. The project files contain the information about which generator tool to use to update the code files from the metadata but again MSBuild does not support it. Any changes to the metadata that is checked-in will not be reflected in the Team Build output.

The idea to have an IDE and a build engine based on the same technology and file formats is brilliant. The need to only manage build settings in one place is the biggest reason for not moving to NAnt or another offering where I'd need to maintain both the Visual Studio projects and the third party scripts manually.

Unfortunately I feel that Microsoft made two major mistakes with MSBuild and Visual Studio:

  • APIs were provided to allow Visual Studio to be extended to support new project items and project types but the API doesn't force the extension to be callable by MSBuild.
  • Microsoft then utilised this API to extend Visual Studio for SQL Server projects and others too and also ignored MSBuild compatibility themselves.
 Wednesday, July 25, 2007

Code Camp SA: Darren Neimke

Remote location On Sunday July 8th, Darren of Readify, and most importantly of Adelaide, closed the inaugural Code Camp SA with a quality presentation. After a couple of false starts it was eventually revealed that Darren would be discussing remote development.

Remote development doesn't necessarily mean sitting atop the Alps with a laptop and some pretty amazing Wi-Fi Internet. It can be a simple as working apart from your fellow development team members such that you can't simply step over to the neighbouring office and discuss your task face to face.

While I generally share an office with the other developers where I work, we do have two offices about thirty minutes apart and I have been working from home on an increasingly regular basis. With this trend likely to continue, the ability to effectively communicate with the team when separated is a growing concern.

In the office I can ask a coworker to look over my shoulder to give a second opinion on some code or we can step over to the whiteboard and represent the problem visually and discuss a solution. In my study at home I have email, I have instant messaging, and I have my mobile phone. These are all excellent systems for communicating verbally or textually but that's where it ends.

I've tried the whiteboard-style collaboration software but drawing class diagrams with a mouse or notebook touchpad just isn't helpful. The other benefit you lose on your own is other team members overhearing your coding pains and butting in with a solution that you probably would have struggled with for much longer before finally asking for help.

Darren demonstrated that having a Tablet PC (or a similar device) can be great for shared whiteboard sessions and new tools like SharedView can help with peer code review or even Pair Programming. I'm not sure what to do about "overhearing" your coworkers apart from a persistent VOIP conference call running in the background and that could be embarrassing when you forget it's on.

Overall, Darren's presentation gave me some good solutions for working remotely and gave me some other ideas to ponder on. And, Darren, if you are reading this, do you have any recommendations for coffee shops with good affordable Wi-Fi Internet in Adelaide?

Touched By PowerShell

Today I was asked how to "touch" all files in a folder in Windows to set the Modified timestamp to now. If I was asked about the Created timestamp I would have suggested to copy the files to a new folder and use the copies which will have a new Created timestamp. Unfortunately Windows doesn't seem to have an easy way to edit the Modified timestamp.

Thankfully, everyone who has Windows also has PowerShell, or should have, or should upgrade their OS. With PowerShell, touching files is easy:

Get-ChildItem * | % { $_.LastWriteTime = [DateTime]::Now }

 Saturday, July 14, 2007

Dirty Pictures

Example roadworks map Frustrated by the lack of up-to-date data for my TomTom, I started poking around the web for various sorts of local information. I discovered that the Department for Transport has a page listing current roadwork sites. Unfortunately, it is only available in HTML form.

Upon inspecting the source however, I discovered patterns in the data suggesting it is automatically driven from by internal database. I asked myself, what is the quickest, easiest, most hackish way I can suck this information into a map? The answer was Google Mapplets.

The result, is an XML Google Gadget that is hosted on my website but runs in the context of the Google Maps site and screen scrapes the DTEI's HTML using JavaScript. Worse Than Failure would be proud.

If you'd like to try it yourself, the gadget xml file is here. You should be able to open Google Maps, click the My Maps tab and choose Add Content where you will be taken to the directory. Choose the Add By URL and paste the link to my xml file.

I might tidy up the abomination that is my JavaScript code if anyone cares enough and submit the gadget to the public Google directory. I am also considering implementing the gadget in Popfly but I am waiting on being able to sign-in to that site.