Time to report back.
I tried the Fez and didn't like it. Nothing technically wrong, but I just didn't like doing my project in managed C#. Having a debugger and emulator was great, but having to think my way out of pointer-based code wasn't. Also, Fez didn't offer a USB host storage solution on the board I was using.
My other option was a VDRIVE2 device. I've got mixed emotions about this one. It works, but it is slow, and the command-based interface is quite clunky. I had expectations of getting a file-system experience like I'd get on a PC. Stupid me, in the absence of an operating system that experience lives only in my imagination 
I'm not sure that the VDRIVE2 is a rugged, production-ready device. A couple of times it has failed to recognise a USB key when plugged in, and I've had to wriggle the key around to get the indicator to light up. If I'm careful when I insert the key I have no problems, but I can't design a product for a workshop environment that relies on "careful" users.
A few hints if you ever use a VDRIVE2:
-
Get the datasheet and the firmware instructions (the command language) from http://www.ftdichip.com/Products/Modules/ApplicationModules.htm.
-
Make sure you reflash the drive using what is referred to as the "Reflash (FTD)" version of the "VDAP Disk And Peripheral Firmware V3.68", or a later version. The firmware shipped with the device is hopelessly out of date, and you'll waste your time trying to get it to work unless you upgrade to a later version.
-
NewSoftSerial is your friend. It was simple to set up a command interface using this library.
-
Ignore any advice you see about wiring CTS and RTS together. In reading files I lost great chunks of data until I went back to basics and implemented these pins. Here's a little bit of code that shows how I used it:
// Send the command to the USB key. Wait a few ms for the
// USB interface to respond.
usb.print (cmd);
delay (10);
// Write any response to the monitor
while (usb.available()) {
// Don't allow the USB interface internal buffer to overflow.
if (usb.available() > 8) {
digitalWrite(usbcts, HIGH);
}
else {
digitalWrite(usbcts, LOW);
}
// Read a character from the USB device
ch = usb.read ();
// Echo character to the serial monitor
Serial.write (ch);
}
To summarise work to date, VDRIVE2 works, but slowly, and with possible physical/reliability issues.
It looks like I'll have to revisit my basic design principles.
I'll look at SD cards, but I don't think they'll be much better than the USB key. Certainly, they're not as user-friendly.
I'll also look at the possibility of plugging the Arduino into the PC and downloading some files onto an embedded (hidden) SD card. The user might bring the device to the PC, load it, then take it back to the workshop.
Back to the code-bench!