Netvibes UWA

Netvibes is a pretty awesome personal homepage web app. It’s very similar to iGoogle, but IMO it’s a lot more stable & a lot better looking. Netvibes offer a unified API that allows you to write using their API and deploy your gadget to multiple providers, such as iGoogle, Opera, iPhone, MacOSX and Vista.

I’ve been writing a gadget for my company but decided I also wanted one to take the first image out of an RSS feed and present so that it takes up all the space in the gadget. Useful for things like LOLcats. It was surprisingly simple to create.. so with some UWA coding, and a simple pipe at Yahoo Pipes, I’m now able to bring in the first image from a specified RSS feed.. assuming the image’s URL has been put into the item.content tag.

Here’s the finished gadget.. and the source code is below…

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<html xmlns="" xmlns:widget=""  >
		<title>Single Image Display</title>
		<meta name="author" content="Matt Collinge" />
		<meta name="author_email" content="" />
		<meta name="description" content="Display an image from the content section of the first item in an RSS feed. Useful for feeds like those from LOLCats. Use Yahoo Pipes to get the image URL (only) into the item.content tag." />
		<meta name="version" content="1.1" />
		<meta name="website" content="" />
		<meta name="keywords" content="image, rss, lolcats, single, full width" />
		<meta name="autoRefresh" content="15" />
		<link rel="stylesheet" type="text/css" href="" />
		<script type="text/javascript" src=""></script>
		<style type="text/css">
			.imageDisplay {
			<preference name="title" type="text" label="Title" defaultValue="Single Image Display" />
			<preference name="url" type="text" label="URL" defaultValue="" />
			var BasicRSSReader = {};
			BasicRSSReader.feed = false;
			widget.onLoad = function() {
				if (widget.getValue('url') === '' || widget.getValue('url') == undefined) {
					widget.setBody('Please edit the preferences and enter the URL of the RSS feed where you want to take the image from.<br><br>The image URL must be in the item.content tag otherwise this will not work. Use feed a reformatter like Yahoo Pipes if you need to tinker with a 3rd party RSS feed such as LOLcats.');
				} else {
					UWA.Data.getFeed(widget.getValue('url'), BasicRSSReader.display);
			BasicRSSReader.display = function(feed) {
				var feedList = 'Unable to load feed.';
				if (feed) BasicRSSReader.feed = feed;
				var item = BasicRSSReader.feed.items[0];
				feedList = '<img src="' + item.content + '" width="' + widget.body.getDimensions().width + '" />';

Using JSLint with Notepad++

I’m doing a fair amount of development using the ExtJS framework. IE is a bit picky about getting JavaScript properly formatted (otherwise it refuses to render the page). That’s why I’ve found JSLint really useful for locating stray commas or semi-colons.

To make it a bit quicker to put the file contents in the JSLint box I decided to hook it up to the Run menu in Notepad++. However, the JSLint web page doesn’t allow us to pass in data to it. To get around this you can copy the HTML + JS files from the authors website an copy them locally. Once you’ve got them locally you can modify the source to allow the passing of data.. here’s the change I made to do it on my system:

jslint.php changes.. add this right near the end

<script src="javascript.js"></script>

You’ll then need a way to take the file contents and fire it off to the page. At first I tried passing the file contents via the GET request, but it’s limited in length. Also, Notepad++ won’t let you send the file contents via the Run command. In the end I chose to use a piece of VBScript to bring up the webpage in the default browser, and some JavaScript to read in the file & place it into the page.


Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(wscript.Arguments(0), 1)

Dim strCharacters

Do Until objFile.AtEndOfStream
    strCharacters = strCharacters + objFile.Read(1)

strCharacters = Escape(strCharacters)

Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objOutputFile = objFileSystem.CreateTextFile("c:\progra~1\notepad++\jslint\javascript.js", TRUE)
objOutputFile.WriteLine("document.getElementById(""input"").value = unescape(""" & strCharacters & """);")

Dim wShell
Set wShell = CreateObject("WScript.Shell")
wShell.Run "c:\progra~1\notepad++\jslint\jslint.html", 9

Finally, this is the Run command you can use in Notepad++ to launch the script…

wscript "C:\Program Files\Notepad++\launchJSLint.vbs" "$(FULL_CURRENT_PATH)"

Switching FoxyProxy Profiles using Script

FoxyProxy is a useful extension to Firefox, but I’m always having to switch profiles back and forth as I take my laptop from work to home, and vice versa. I experimented with proxy PAC files without any success (mainly because laptops have multiple network adapters and the PAC scripts only detect your first IP address). Plus, as far as I can tell, PAC files are checked for every single HTTP request which must be a hit on browser performance.

Anyway, what I decided to do was directly modify the FoxyProxy config file before Firefox was run, and this would then select which FoxyProxy profile was used. The script below detects the host of something on my local network (which doesn’t exist at work) and switches accordingly. You could get it to switch on anything you like, but this works for me.


Set WshShell = WScript.CreateObject("WScript.Shell")

' Code to determine where you are and switch profiles accordingly
if (Ping("somehost") = "") then
end if

' Run Firefox - this uses a specific profile.. your command line can simply exclude it
ReturnCode  = WshShell.Run("""C:\Program Files\Mozilla Firefox\firefox.exe"" -profile ""z:/firefox/profiles/qtxjee58.default""", 6, False)

sub ModifyFoxyProxy(sProfile) 
	' Path to your foxyproxy.xml file
	set oparser=createobject("msxml2.domdocument")
	with oparser
	    .load xmlfile
	end with
	if oparser.parseerror.errorcode<>0 then
	    wscript.echo "xml file " & xmlfile & " is not well-formed." & vbcrlf & "Operation aborted."
	    wscript.quit 999
	end if
	set oroot=oparser.documentElement
	oroot.setAttribute "mode", sProfile outfile
	set oparser=nothing 

end sub

function Ping(strHost)

    dim objPing, objRetStatus

    set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery ("select * from Win32_PingStatus where address = '" & strHost & "'")

    for each objRetStatus in objPing
        if IsNull(objRetStatus.StatusCode) or objRetStatus.StatusCode<>0 then
    		Ping = ""
            'WScript.Echo "Status code is " & objRetStatus.StatusCode
            'Ping = True
            'Wscript.Echo "Bytes = " & vbTab & objRetStatus.BufferSize
            'Wscript.Echo "Time (ms) = " & vbTab & objRetStatus.ResponseTime
            'Wscript.Echo "TTL (s) = " & vbTab & objRetStatus.ResponseTimeToLive
            Ping = objRetStatus.ProtocolAddress 
        end if
end function 

USB Detect & Launch Version 1.5 Released

USB D&L USB Detect & Launch allows you to automatically execute a script or application each time a USB storage device is plugged into your PC. Different scripts can be executed for different devices and it’s the volume label that determines what action to perform.

Version 1.5 contains new functionality to monitor for any device being plugged in; useful when you have no control over what memory stick is being inserted, but need to fire off a script to perform a particular action.


exec:”c:batchbatch-any.cmd” %1 %2

You can find the download on the USB Detect & Launch page.

Drive Map Pro 1.6 Released

Drive Map Pro is a great piece of Windows software for organising all the servers you connect to. It’s primary purpose is to give you easy access to mapping a network drive with the minimum of fuss, however it does a lot more that that, including managing your VNC/Radmin connections too!

The latest version of Drive Map Pro (version 1.6) is now available to registered users and includes the following:

  • Lots of bug-fixes :-D
  • Ability to have multiple UNC drive mappings under one entry, syntax is ‘\serverc$,d$,whatever’, which gives you the ability to map to any/all 3 of those drives without clogging up your list of servers!
  • Middle-click launches the application you’ve associated with the server.. saves a click or two!
  • Store notes against each entry.. handy for storing box info, like who’s the administrator
  • More application preferences (like auto-hide DriveMapPRO after launching an application)

Click here for more information on Drive Map Pro.

Drive Map Pro 1.6

Mapping a drive has never been easier!!

Topfield TF5800 – a hacker’s PVR :)

The Netgem iPlayer I’ve had for watching Freeview doesn’t provide any PVR functionality, so I’ve been looking for a replacement that does everything I want. It was between the Humax 9600 and the Topfield TF5800. After a lot of research I went for the Topfield.

The thing that swung it for is that the Toppy is extremely configurable due to 1) the custom firmwares 2) the user-built applications (TAPs) that are available.

Between the firmwares and the TAPs you can customise almost anything! For example, on the standard box the display on the front will show the time when in standby, and the channel number when it’s switched on. That’s not something I care for.. I can see the channel I’m watching and the time is more useful to me. Someone else obviously thought the same, and they’ve created a TAP (TF5000Display) to completely customise the display to your needs, doing way more than what I needed.

First Things First

Setting the box up wasn’t as arduous as I thought it was going to be. After rigging it up to the TV and making sure everything worked, I fired up my laptop and installed the Topfield Tools suite, together with the USB Driver for Windows XP. Easy so far.


Next I downloaded the firmware I wanted to install. This was from and required me to sign up for their forums, and that gave me a login for the main site that brings up a new menu where you can download new (and beta) firmwares. I chose the 5.13.65 release which was recommended by the site.

The firmware can then be (optionally) patched with extra fixes which have been community-written. To work out which ones I wanted to integrate into the firmware I read this topic and downloaded FWPatcher & PatchPackV2 which contained everything I needed.

The patches I chose were:

  • [C0] NoCYR
  • [Cy] NotCYR_02
  • [H] HDDPatch_03
  • [I] PBSiS
  • [P] PowerRestore_05
  • [R] RecRoundel
  • [S] StartupPatch_03
  • [T2] TimerPatchT2b
  • [Ts] TimerSetting_02
  • [T] TimerPatch_04b
  • [Wf] WindFaster_02
  • [Xp] PlayNoCYR_04
  • [Xw] WatchNoCYR_03
  • [Z] Disable0AspectSwitching

After integrating the patches the next step was to blow it onto the Toppy using the firmware utility in Topfield Tools.

The process was surprisingly easy and the online documentation is good if you get lost.


There’s only so much you can stuff into 1.5mb of firmware, and Topfield were considerate enough to allow people to program applications, a bit like plug-ins, which have access to an API provided by the company. That allows these programs to access things like EPG data or write out to the screen.

The standard EPG that ships with the box isn’t great.. but add the MyStuff TAP and the unit is completely transformed with a highly customisable, and skinnable EPG. There’s even a 71-page PDF manual for MyStuff! Here are 3 things you can customise (out of a list of maybe a hundred):

  • Show/hide channel logos
  • Choose how many hours to display in the EPG window (3hrs seems sensible)
  • How many channels to display per EPG page (8 suits me!)

The TAPs I added on day 1 were:

  • MyStuff (which adds a few of it’s own, including one that scrapes EPG data)
  • Display
  • PowerDown
  • TAPCommander


The standard Topfield box is okay. And it’ll probably be a lot better with the new firmware that will be released shortly that features in the new TF5810 and conforms to the Freeplay standard. However, with the custom firmware and TAPs (especially MyStuff) the box is awesome and I’m having a great time configuring it to be exactly what I want from a Freeview PVR box. Kudos to the user-community who put so much time into developing the patches and TAPs!! And thanks to Topfield for being forward-thinking enough to open it up enough to allow these mods to be written.. if only more manufacturers did this!!!

Quick Video Demo

This is a demo showing what the Topfield PVR looks like once the MyStuff application has replaced the standard UI.

At the start of the video you’ll see the default Toppy UI, then I fire up MyStuff where you’ll see the difference straight away.

After viewing the EPG I navigate around a bit, then show a MyStuff settings page to give you an idea of how many things you can configure.

I go on to show a few more things including setting series link (via a Search), and a some of the standard Topfield things like pausing live TV, PiP, etc.

Near the end I dip into TAPCommander which helps you configure any user-written apps you’ve got loaded into memory.

This covers only a small portion of what the box is capable of and is only meant as a taster :)

File Mover 1.8 Released

New features in this release are:

  • Force “first-in, first-out” queueing of files.. files will be processed in date order (oldest first).
  • Wait for executed script to finish before processing the next file (useful when FIFO queue is being used, or when your script is so intensive you don’t want >1 process running)

Click over to the software page for the download.

XBMC Script – Caller Id 1.3 Released

This script for XBMC allows you to display details of incoming calls. Full details on how to get this up and running are on this page; you’ll need the right kind of modem attached to a PC running software like YAC.

The latest versions of the Caller Id script now include:

  • Play a sound when a call is displayed (optional)
  • Support for Switchboard by James Traynor merged into this release
  • Small bugfixes around which name to display
  • Better logging so it’s easier to debug when things go wrong :)
  • Pause playback option (optional)
  • When YAC has passed a name, display that rather than the number
  • Display an initialisation message when script starts (optional)
  • Code to allow this to run in Python emulator on a PC

You can find the script at

USB Detect & Launch Version 1.4 Released

USB D&L This new version includes the ability to detect when devices with no label are inserted. This is handy when you have a whole stack of new devices that you need to put data onto.

Here’s an example of the syntax you’d use:

label:(no label)
exec:”c:\batch\batch-no-label.cmd” %1 %2

Click over to the software page for the download.

New App: Screen Saver Killer

Some businesses enforce a corporate policy whereby your screensaver is set globally and is locked down so that you can’t change the settings.

In a whole bunch of scenarios, this is the last thing you want. Here are a few examples:

  • During a presentation consisting of a video, the screen saver will activate after the period defined by your IT department
  • On the big screens they put up on walls to show corporate messages/stats/etc you don’t want the screen saver activating when these screens are driven by a PC which is logged into a user account.
  • You’re not working on your laptop, but have the screen open so that you can keep an eye on your inbox, or a system monitor tool. If the screen saver kicks in every 10 minutes it can get very tedious unlocking the thing each time >:-(

Screen Saver Killer is a very simple app that will give you back control over your screen saver settings.

Click through for the download.

Spoken Caller Id on your PC using YAC

My project to get Caller ID detected on a PC off a UK landline is nearly complete. Click here to read about the full project, which includes finding a compatible modem, sending the caller ID to other PCs (or XBMC) on your network, and generating an RSS feed of incoming calls.

On my gaming box, the standard YAC notifications for a new call won’t be seen whilst I’m actually in a game:


Having the option for the PC read out the caller information would overcome this. YAC in it’s current incarnation (v0.16) doesn’t support speech, but fortunately the author has made the source code available under the GPL :-)

Extending YAC

The changes I made to YAC were kept as generic as possible (i.e. they’re not specifically tied to text-to-speech). When an incoming call is detected by YAC it does the usual notifications, but also executes a script called yac-helper.cmd (if it exists in the same folder as yac.exe).

Parameters are passed into yac-helper.cmd that enable you to do whatever you like with the incoming call. In my case, I’m simply passing control to a piece of VBScript that instantiates the Microsoft text-to-speech engine.

Sample Scripting

Here’s some sample code (which is included in the unofficial YAC 0.17 build I’m hosting on this site):


@echo off

rem  ----------------------------------------------------------
rem  Matt Collinge :: :: 17 April 2007
rem  ----------------------------------------------------------
rem  Helper Script for YAC 0.17. When present in the same 
rem  folder as "yac.exe" this will be run each time a call is 
rem  received. The type of data being passed through 
rem  in %2 &amp; %3 is specified in %1. 
rem    %1 = ( call | message )
rem    %2 = either the calling number or text-based message
rem    %3 = the calling name (not set for a text-based message)
rem  ----------------------------------------------------------

rem This next line simply passes the parameters on to a piece of VBScript. But you can
rem modify this line to call any app you like :)

wscript "c:\\yac\\yac-speech.vbs" %1 %2 %3


' --------------------------------------------------------
' Matt Collinge :: :: 17 April 2007
' --------------------------------------------------------
' Take an incoming call from YAC and use the default voice
' to speak it back to the user.
' --------------------------------------------------------

Dim voic
Dim message
Dim messagePrefix

calltype = WScript.Arguments(0)

Set voic = WScript.CreateObject("SAPI.SpVoice")
Set voic.voice = voic.GetVoices("", "Language=809").Item(0)

select case calltype
	case "call"
		sNumber = WScript.Arguments(1)
		sName = WScript.Arguments(2)
		if (sName = "No Name") then
			messagePrefix = "Incoming call from number "
			message = sNumber
			messagePrefix = "Incoming call from "
			message = sName
		end if
	case "message"
		message = WScript.Arguments(1)
		messagePrefix = "Incoming message "
end select

voic.Speak(messagePrefix + message)

Set voic = nothing

Job Done

When an incoming call is sent to the YAC listener on my gaming PC, it will fire the scripts above and text-to-speech allows it to read out the caller info. Dead simple really.


The default voices that are installed with XP are pretty basic, but you can buy others that sound spot on. Try out the AT&T Natural Voices demo for an idea of how good it can sound.


Below you’ll find an unofficial build of YAC 0.17 (which I’m hosting until the original author integrates similar changes into the main build). Full source code for this build is also available, and is licensed under the GPL.

YAC 0.17 binaries for win32 (tested on XP)
YAC 0.17 source code

Build 0.17 Installation Instructions

I couldn’t be bothered creating an installer for this unofficial build. You’ve read this far so you must like messing with code, and don’t mind extracting a few files from a .zip

  • First off install 0.16 from the original author’s website
  • Next, simply extract the files in the binaries .zip file over the top of the 0.16 files
  • Edit yac-helper.cmd to your liking (including the path to yac-speech.vbs if you’re trying this example)
  • Run YAC and try testing the listeners to see if everything works

Caller Id Revisited

For a while the caller id project has been on the back burner as I’ve been working on other things and have upgraded my gaming PC. I’ve now got the time and inclination to revisit the caller id project in an attempt to get a reliable/working solution.

The aim of the project is to detect an incoming phone call and do the following:

  • Log the call to an RSS feed (useful for knowing when someone important has tried to contact me whilst I’m at work)
  • Broadcast the caller id info to devices on my network. This includes the Xbox running XMBC and CallerIdLite, a couple of laptops, and a gaming PC.

Detecting an incoming call is achieved by attaching a suitable modem to a server & have the PC log the call.

Although I initially had the US Robotics modem working, it suffered from the DSR Drop problem and I never did get a permanent fix :( In the end, I sold it on eBay and bought a different brand.

I’m now using an external Pace 56 Voice Modem (firmware drivers available here and modified modem driver that supports calller id in the UK here) which works perfectly and gives me an opportunity to complete this project.

Now that the incoming calls are reliably detected and the caller id is being distributed across devices on the network using YAC, the one thing left to perfect is the notification on my gaming PC. In a game the standard YAC popup won’t be visible, therefore the ideal solution is for the id to be read out using text-to-speech :-)

YAC doesn’t currently support this kind of thing, but fortunately the guy who wrote it made the source code available under the GPL. My next post will cover how I’ve extended YAC to do text-to-speech.

USB Detect & Launch Version 1.3 Released

USB Detect & Launch has been enhanced to allow you to execute a custom script from the system tray menu. The option appears only when you’ve inserted the USB device. The idea behind this is that after the initial insertion event you can fire an automatic script to perform an action, then before you eject it you can use the system tray menu to fire off another script.

To use this feature, simply add a line under your device called menurun. E.g.

“c:\win32app\startup\batch-insert-pendrive.cmd” %2
menurun:”c:\win32app\startup\batch-eject-pendrive.cmd” %2

One utility you might find useful to use in conjunction with your scripts is USBDeview. This will allow you to issue a ‘Safely Remove Hardware’ command from your script.

Click over to the software page for the download.

Full Podcast Download Automation

In my last post I chose Juice (formally known as iPodder) to keep me up-to-date with the latest podcasts. It downloads the latest episodes and sticks them into a folder when they’re complete. Since this runs on my server I don’t know when the download is ready, and I also have to plug in my MP3 player and copy them over manually.

In an Ideal World…

Wouldn’t it be great if I was notified when the download had completed and could simply plug in my MP3 player and the PC copied over the files automatically? There didn’t seem to be anything out there that automated things to this degree so I decided to roll my own. Here’s what should happen:

  • Podcast app downloads new episodes from the RSS feeds I’m subscribed to
  • Podcast app should update my ‘completed downloads’ RSS feed with the latest podcast (this feed is read on my desktop at work). This is achieved through a simple script that’s executed when the download completes.
  • If the podcast app doesn’t support scripts and you’d like to reorganise the downloaded files or run a script, then use File Mover as an intermediate step.
  • Detect when a USB storage device is inserted
  • Based on the USB device’s label, run a specific script, which in this case will move .mp3’s to my MP3 player, and move video episodes of Diggnation & Hak5 to a USB memory stick so that I can get them on my laptop with the minimum of fuss.

Basic flow

The New Application

Detecting a USB storage device and running a specific script based on it’s label isn’t something I found an application for. That’s when wrote my own app to do exactly that.

Like with most of my utilities, the program is quite simple, with the power coming from being able to fire off a script which you can do almost anything with. In this case I’ll write a simple script to copy over any .mp3 files onto my appropriately labelled MP3 player, and anything else goes onto my 2GB USB stick.

The new app is called USB Detect & Launch and is available here for download. It’s effectively a beta, so give it a try and let me know whether it works for you!

Putting It All Together

1) Install Juice (or whatever app you’re going to use to subscribe to podcasts with)

2) Add the RSS feeds for the podcasts you want into Juice. E.g. Diggnation has them listed on the right hand side of the page, just pick the type of file you want (MP3, WMV, Xvid, etc).

3) Set up the destination folder for the downloaded podcasts

4) Set up the download schedule so that new podcasts are automatically downloaded

If you want to use RSS to inform you of newly downloaded podcasts follow the next steps, otherwise skip to step 8.

5) Write a quick script to add a few lines into our ‘completed downloads’ RSS feed so you’ll know when a new podcast is available even when you’re not near your server.

6) Add the script to Juice. Note; if you’re using another app that doesn’t support scripts in this way, then you can easily use File Mover as an intermediate step.

7) Setup your LAMP/WAMP installation to use a PHP script that will generate the RSS feed of completed downloads. The PHP script parses the logfile written by the script in step 5 and makes it into a simple feed.

Back to the automation…

8 ) Install and configure USB Detect & Launch. For each USB device you want to sync to, build up a simple script using the volume name, and the script you want to execute when the device is inserted.


exec:wscript “c:\backup.bat” “%1” “%2”

exec:wscript “c:\batch\copy-to-mp3-player.bat” “%1” “%2”

%1 is replaced by the drive letter of the attached device (e.g. e:\)
%2 is replaced by the volume label of the attached device (e.g. PENDRIVE)

9) Write the script that’s called from USB Detect & Launch. The scripts can be as complex as you need them. A simple example would be to copy all the files from one of your podcast folders to your MP3 player using a batch script like this:

rem backup.bat
rem —————————————-
rem USB Detect & Launch will put the drive
rem letter of the USB storage device into %1
rem —————————————-

copy /Y “c:\podcasts\hak5\*.*” %1

Or maybe using xcopy to move all the sub-folders (/S) over would be better. Xcopy’s other options (/M) also allow you to copy over files with the Archive attribute and can reset this attribute after the copy.. essentially only copying the files over once, whilst keeping a copy on your hard drive:

xcopy f:\podcasts %1podcasts /M /S /Y

For more advanced copying of files, try using Robocopy with the Robocopy GUI app to help build up the command’s parameters.

Test The Setup…

10) That’s it. Start up Juice, and start USB Detect & Launch.

Test the process by subscribing to a new feed of podcasts. Let Juice download the latest episode automatically. When the download has completed you should find the file added to your RSS feed:

At this point you can insert your USB device and it should be detected & your podcasts will be copied over using the batch script you’ve written.

Simple 8)

PC Virtualisation

Using a technology such as Microsoft’s VirtualPC is ideal for developers. In a nutshell, it allows you to run a virtual copy of Windows 98/2000/XP on your desktop.

In the screenshot below you’ll see my local copy of XP running a virtual copy of XP. The progress bar is showing a file being copied over to the desktop of the virtual PC after I dragged it in there from my PC.

For me, the benefits of using this type of software are:

– Older operating systems such as 98, NT4, and 2000 can be run without the need for multi-booting. This is great for testing your app works on legacy PCs.

– You can work on your normal desktop and switch to the virtual PC as if it’s another windows app.

– Each virtual PC can be setup to discard changes when you’re shutting it down; this is ideal for trying out software in an environment you can reset to a pristine state afterwards.

– The virtual hard drive for each PC is kept in a single file on your proper PCs hard drive. This makes it very easy to backup, or copy onto another PC (OS license permitting).

– The VirtualPC software is completely free! (but it does require you to have the relevant OS licenses for each virtual PC you create).

All in all it’s a good piece of software to try, especially if you’re a developer who doesn’t have a host of PCs to use as a test suite.