Overvalidation

Updated on Saturday, July 18, 2020

Overvalidation is unhelpful error checking, usually caused by an over-zealous engineer with insufficient domain knowledge. My blood pressure has suffered from two cases of overvalidation this week.

I bought a new NAS — the Linksys NAS200 to set up RAID 1 with a couple of 1TB drives.

I was delighted to discover that the NAS could send email when it detects a problem or starts running out of disk space. Except it couldn't because someone decided that an email server could live at port 25, or at port 1024 or higher.

My ISP blocks port 25 - maybe to cut back on bot spam, maybe because their support staff are bored and lonely. This is far from unique and it's common for email providers to offer an alternative port. Which is almost always port 587. I tried to put a bug report into Linksys but their support pages effectively said "dude, you paid $89 for this box, go talk to other losers on some forum".

Linksys NAS Email Alert Fail

The NAS problem can be solved by redirecting a port on my router. I haven't figured out how to deal with Technorati yet. After spending seemingly months moving their datacenter they've evidently done some work on their blog claim process. I created a new blog yesterday (Webcam Updates, to remove some clutter from the main Catfood Blog) and went over to Technorati to claim it.

When you enter a URL like "http://www.site.com/blog" it's automatically changed to "http://site.com/blog". Which is a different URL. I 301 redirect any "catfood.net" url to "www.catfood.net" to prevent getting dinged by Google for duplicate content. Technorati's claim process fails if there's a 301 redirect.

Technorati Blog Claim Fail

I guess I could remove the redirect, complete the claim and then hope that I can put the redirect back without breaking Technorati. Possibly when my blood pressure is back to normal.

Please, by all means do some validation – "giraffe" is most certainly not a valid TCP/IP port – but don't overvalidate, and don't assume that your mail server port or preferred URL convention is some kind of universal constant.

Fastest image merge (alpha blend) in GDI+

Updated on Wednesday, December 19, 2018

Blended image from Catfood Earth

I've been experimenting with the best way to merge two images in C#. That is, paint one image on top of another with some level of transparency as opposed to using one color as a transparency mask. I tried three candidates, all included below:

SimpleBlend is the naive approach using GetPixel and SetPixel to add the desired alpha value to the second image before painting it on top of the first.

MatrixBlend configures a ColorMatrix to specify the desired alpha and then paints the second image on to the first using the matrix.

ManualBlend locks and directly manipulates the image data. This uses pointers and so introduces unsafe code (it's possible to marshal the image data into a managed array but I wanted to look at the performance with raw access).

I tested each approach ten times with a couple of large JPEG images. The results are:

SimpleBlend: 17.69 seconds
MatrixBlend: 0.74 seconds
ManualBlend: 1.13 seconds

I expect ManualBlend could be optimized further but both this and MatrixBlend are an order of magnitude faster than the naive approach. I'll be using MatrixBlend as no unsafe code is required.

Año Nuevo

Updated on Saturday, July 18, 2020

Año Nuevo

We decided to visit Año Nuevo State Natural Reserve today because it's one of the hundreds of California state parks threatened with closure by Governor Arnold Schwarzenegger's proposed cuts.

The main attraction of Año Nuevo is the presence of a large colony of elephant seals. At this time of the year you walk a couple of miles where volunteers are available to answer questions and lend binoculars. In the breeding season between December and March you need to book a guided walk at least a day in advance - or at least you will if the park survives.

(As well as my video, check out the streaming Sealcam on Año Nuevo Island.)

Elephant Seals at Año Nuevo

Elephant Seals at Año Nuevo.

Gill with Año Nuevo Island in the background

Gill, with Año Nuevo Island in the background. You can see the ruins of a lighthouse on the island (click the image for a larger version). The original name dating back to 1603 is La Punta de Año Nuevo or New Year's Point (much erosion since then).

A Lizard

One of many lizards encountered on the trail.

(4.18 miles, total elevation gain 268 feet, 1 hour, 48 minutes, average 2.32 mph, view in Google Earth, view in Google Maps.)

Hike starts at: 37.12086, -122.307237.

MessageInterceptor doesn't always...

Updated on Sunday, May 3, 2020

I've been writing a play by text message version of battleships for Windows Mobile 6 using the MessageInterceptor class to receive messages. This works great on my AT&T Tilt but completely fails on my wife's Pantech device. The MessageInterceptor hooks up fine but never fires.

The 2.0 compact framework SmsAccount lets you send messages but unaccountably doesn't let you read them.

I avoided some unpleasant interop by grabbing the MAPIdotnet library. This implements a NewMessage event for MAPI stores, however as with MessageInterceptor the event hooks up OK but never fires on the damned Pantech.

MAPIdotnet does allow you to read the SMS inbox though, so the final answer is to fall back to looking for, processing and then deleting game related text messages on a timer. This is far from ideal as the game messages arrive and vibrate the phone before getting processed but at least it's now possible to play without buying a new phone.

To add to the frustration during development the Visual Studio 2005 toolbox lost all icons except for the pointer and a custom control that was part of the project. Resetting the toolbox didn't help, nor did restarting VS and the computer. The fix was to exit VS and then delete all the .tbd files from Microsoft\VisualStudio\8.0 in local application data. Sigh.

Launching a URL in the user's default browser

Updated on Sunday, May 3, 2020

This has bitten me a few times. If you use Process.Start("url") it will work some of the time but you'll see a "The system cannot find the file specified" Win32Exception on some systems. Bummer.

Lots of people suggest looking up the HTTP handler in HKEY_CLASSES_ROOT but this is flawed as well - on my system for instance HTTP is registered to Firefox even though I'm actually using Chrome and I'd be unhappy waiting half an hour for Firefox to wake up and show the requested web page.

From XP there are a couple of registry settings tied to the current user's preferred browser.

First check HKEY_CURRENT_USER\Software\Clients\StartMenuInternet. This key will only exist if the user has overridden the system default browser - the default value is used to access the details (for me, it's chrome.exe).

If the user hasn't set a default then check HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet. The default value here is the system default browser (on my system it's FIREFOX.EXE).

There is a set of subkeys under HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet that contain details about each registered browser. The default value from StartMenuInternet (either HKCU or HKLM) is the subkey to look for. The path to my default browser is in this key:

HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet\chrome.exe\shell\open\command

Now I can Process.Start(path, url) to safely launch the default browser. You can fall back to Process.Start(url) if registry access fails for some reason, but be prepared for that Win32 exception.

WiX Tricks for Screen Savers

Updated on Tuesday, May 26, 2020

I've been migrating my installers over to WiX. My only complaint with the WiX toolkit is that there's no bootstrapper included. This is important for installing any pre-requisites before passing control over to Windows Installer. Hopefully this will come after WiX 3.0 is released. For now, I've rolled my own bootstrapper to install .NET 2.0 if needed.

A couple of tips for screen savers. You can bring up the Windows screen saver settings using the following custom action. This is the same command that is launched when you right-click a screen saver (.scr) file and pick Install:

<CustomAction Id='InstallSS' Directory='SystemFolder' ExeCommand='rundll32.exe desk.cpl,InstallScreenSaver the.scr' Return='asyncNoWait'/>

Sequence this in InstallExecuteSequence after InstallFinalize:

You can also add a shortcut to your Program Files folder to configure the screen saver. This is really helpful for people who aren't sure how to get to the screen saver dialog from Control Panel or right-clicking the Desktop:

Unlike a shortcut to a file that you install you need to specify the Target. The example above assumes that ProgramMenuDir is the Id of your Start Menu folder. The shortcut should be in a Directory but not as a child of a File node.

Updated 2020-05-26 20:22:

It looks like something changed in Windows 10, around build 1903, that stops this from working on 64-bit systems. The screensaver will preview OK but does not start as expected (system screensavers start OK, so it's not some sort of power management problem). I could reproduce this on one box running 1909 but not another so maybe there is something else going on. The snippets above will run rundll32.exe from the SysWOW64 folder and at some point this seems to have stopped working. Changing to [System64Folder]rundll32.exe launches the System32 version which then causes the screensaver to load normally. If your screensaver is 32-bit and installed to SysWOW64 then you need a command that looks like this on a 64-bit system: [System64Folder]rundll32.exe desk.cpl,InstallScreenSaver [SystemFolder]the.scr

code, c#

The Perfect Twitter Client

Updated on Sunday, May 3, 2020

I started using bDule today after reading about it on Techcrunch. It seems to be very nearly the perfect twitter client for me - decent multi-account support, Facebook integration and reasonably snappy. Also, and this is really important for me, it's not oppressively black.

The group feature isn't quite there yet, it doesn't list all my friends and there's no way to edit a group after you create it. There's also no spell checker and getting the right layout is unnecessarily awkward. It's still in alpha so there's good reason to hope that these problems will be addressed soon.

I wonder where the name comes from. It makes me think of a certain casual game where you swap gemstones around until you're ready to chew your eyeballs out. I'm the last person to talk about puzzling software names though.

bDule is WPF/.NET3.5 so only runs on Windows XP or better. It also seems to suffer from the same creeping memory usage that plagues other desktop Twitter clients. I really wish someone would start offloading the stream into a database. I've got nearly frustrated enough with this to write my own Twitter client a couple of times, but it's not exactly an uncrowded market.

If you're a Windows tweeter give bDule a try.

Video timeout on XP and Vista (power management)

Updated on Sunday, May 3, 2020

I'm updating a screensaver so that it stops work once the monitor switches off. This seemed like a really simple requirement but it took some time to find an API that works on both XP and Vista.

My first attempt was ReadPwrScheme(). The documentation suggests using a different method on Vista - it should say so more strongly because on Vista you get back some default information that bears no relationship to reality.

Next I tried CallNtPowerInformation(). This doesn't mention any alternatives but also doesn't work on Vista. I've added comments on both MSDN pages pointing to the answer.

GetCurrentPowerPolicies() is just the ticket - it returns a wealth of information including the video timeout on AC and battery power and works on both XP and Vista.

Pinvoke.net has all the structures required but not the actual function. I've just added the C# interop signature for GetCurrentPowerPolicies().

I can't believe how frustrating finding this information has been. If you've found this post I hope it saves you a couple of hours :).

Point Reyes - Tomales Point

Updated on Saturday, July 18, 2020

Tomales Point in Google Earth

Tomales Point is a ten mile hike in Point Reyes. The trailhead is at the end of Pierce Point Road. It's my least favorite topological combination — the trail is mostly downhill on the way out and at the end you turn around and come back. It's worth it for the views of Tomales Bay and the Pacific, also for the flora and fauna along the way.

We did this hike a few years ago with my parents, thinking that we'd avoid some approaching rain. Of course the heavens opened as soon as we reached Tomales Point and it rained solidly for the five mile return leg. I remember emptying water out of boots and pockets and then steaming up the car for the two hour drive back to San Francisco.

Long-tailed Weasel

A Long-tailed Weasel at the start of the trail. It kept running away and then coming back to take another look at us. Very cute.

Rob & Gill at Tomales Point

Rob and Gill at Tomales Point. It was too windy to find a spot to get the camera to take a photo of both of us at the same time. Tomales Point looks out to Bodega Bay where The Birds was filmed.

Some sort of silver thistle thing

This plant looks like a silver thistle with a bright red flower. If you know what it is please leave a comment and let us know! Lots of people were in garden-center mode for the hike, admiring the incredible variety of spring flowers along the trail.

Turkey Vulture

A Turkey Vulture, hoping that we don't make it all the way back to the car…

Tule Elk

Tule Elk, native to California and slowly recovering from near-extinction in the late 19th century.

(9.77 miles, total elevation gain 241 feet, 3 hours, 39 minutes, average 2.67 mph, view in Google Earth, view in Google Maps.)

Hike starts at: 38.189931, -122.955497.

Lands End

Updated on Saturday, July 18, 2020

Lands End

Lands End to Eagle's Point is a stunning section of the Coastal Trail. Park in or near the new lot at Point Lobos Ave and El Camino del Mar. Before or after the walk check out the ruins of Sutro Baths. I'd put some of that American Recovery and Reinvestment Act cash into rebuilding the baths, it looks like they were incredible.

Sutro Baths

If you follow the trial down the the baths then there's a short but very cool cave to explore which ends in another unique view of the pacific and the mouth of the Golden Gate.

Golden Gate Bridge

From Sutro Baths follow signs to Eagle's point. There are some very steep cliffs along the trail, so a leash is a really good idea for dogs.

Rudy & Gill on the coast trail

One worthwhile detour is to wonder down to Mile Rock Beach. It's a stony and impressively violent beach with a couple of lookouts on the way down with impressive views.

Rob & Rudy at Mile Rock Beach

(3.16 miles, total elevation gain 457 feet, 1 hours, 24 minutes, average 2.24 mph, view in Google Earth, view in Google Maps)

Hike starts at: 37.783491, -122.510793.