Saturday, December 25, 2010

How to solve “My PC Randomly Wakes up from Sleep”

Whenever your PC wakes up, Windows keeps a log of why. To view, open a command line and run:

 C:\> powercfg -lastwake
Wake History Count - 1
Wake History [0]
  Wake Source Count - 1
  Wake Source [0]
    Type: Wake Timer
    Owner: [PROCESS] \Device\HarddiskVolume3\Windows\System32\services.exe
    Owner Supplied Reason: Windows will execute '\Microsoft\Windows\Media Center\mcupdate_scheduled' scheduled task that requested waking the computer.

As you can see, my computer woke up because of a scheduled task. Open the Task Scheduler: image And navigate to the task in question (\Microsoft\Windows\Media Center\mcupdate_scheduled, in my case). On the Conditions tab, uncheck wake: image

Friday, December 24, 2010

Why Developers Always Need to use UTC

Assert.AreEqual(new DateTime(2010, 11, 07, 06, 0, 0, DateTimeKind.Utc).ToLocalTime(),
new DateTime(2010, 11, 07, 07, 0, 0, DateTimeKind.Utc).ToLocalTime());

Because when we fall back from Daylight Saving Time, the hour of 1am is repeated, making it ambiguous. Which is why the above test code passes in Central time, since 6am and 7am UTC are both 1am, one 1am CDT, the other 1am CST.

Monday, December 13, 2010

Using XML Namespaces in PowerShell

$xpath = @{
    Start="//e:data[@name = 'BootStartTime']/text()"
    End="//e:data[@name = 'BootEndTime']/text()"

$ns = New-Object Xml.XmlNamespaceManager $xml.NameTable
$ns.AddNamespace( "e", "" )

[DateTime]$Start = $xml.SelectSingleNode( $xpath.Start, $ns ).Value
[DateTime]$End   = $xml.SelectSingleNode( $xpath.End, $ns ).Value

($End - $Start).ToString() # Displays: 00:03:11.7917783


Wednesday, December 08, 2010

Full IIS Mode at Windows Azure

One of the nice new features in the December 2010 release 1.3 of the Azure tools is Full IIS Mode, the ability to run multiple web sites in a single Azure web role. The documentation is a bit sparse still, but the short answer is to add multiple <site/> tags in the ServiceDefinition.csdef.

Here's a good post on the Azure blog, and here's some documentation at MSDN.

<Site name="<web-site-name>" physicalDirectory="<directory-path>">
      <Binding name="<name-of-the-binding>" endpointName="<endpoint-identifier>" hostHeader="<url-of-the-website>" />

Tuesday, November 30, 2010

Task Scheduler Engine

This past weekend I published a small open source project at CodePlex, Task Scheduler Engine. It is a simple cron-like scheduling API with a clean fluent interface (also supports XML config, if you prefer typing out assembly qualified names). Use it when you need a simple, in-memory scheduler and when you need tasks to execute at a specific second (in other words, if you start doing math to compute the duration of your timer so that it fires at a specific time, use this instead). If you have multiple services load balanced to execute tasks, this isn’t for you.

Here’s all that’s required to schedule a task (write console output) to execute every ten seconds:

var s = new Schedule()
    .AtSeconds(0, 10, 20, 30, 40, 50)


Creating your own tasks is just as easy—implement ITask, which has an Initialize method and a Handle method that is called at the scheduled time.

It compiles to an 18KB assembly, has no external (non-framework) dependencies, and is just over 250 lines of code. Add clean, simple scheduling to your .NET application.

Sunday, November 14, 2010

Travis Cooks

I started a new blog over at Imagine me with a cameraphone uploading quick summaries of what I'm cooking.

On the subject of food, I run, a site where I drop all of my knowledge and research about kefir. If you don't know what kefir is, it's a wonderful probiotic fermented milk beverage—imagine a super yogurt.

Wednesday, September 15, 2010

Learning a new Keyboard Layout

A friend of mine asked me about how I learned Colemak and I sent him this email; thought I’d flesh it out and share.

  • Decide on layout
    • Colemak was the best I’ve found given I already touch-typed QWERTY
    • Go here, paste in a bunch of text that you’ve typed, and then look over the analysis on how far your fingers would have to move in order to type it:
    • For this email (minus this bullet), Colemak is the best mainstream layout (32.68meters of finger travel), Dvorak 2nd (33.39m) and QWERTY the worst (51.86m). Again, for me, given the amount of similarity to the QWERTY layout, Colemak became the obvious choice for me.
    • Do your own research and look for some of the ergonomic studies that are out there.
  • Typing tutor software to help you learn
  • Making the switch
    • I practiced with TypeFaster in the evenings until I could type with mid 80s% accuracy and ~20wpm. That took a month, maybe more.
    • Then, I went cold turkey. It was painful. I couldn’t really type in either Colemak or QWERTY. My thoughts got stuck and couldn’t get out of brain and into the keys.
    • You will get here, you will feel the emotional agony, and you must move forward. Stick with it.
    • If you are thinking about they layout as a “letter-to-key” lookup map (which is naturally how you start), you need to switch to thinking about “speaking with your fingers.” It’s hard to explain, but as the thoughts form as words in your mind, you can’t think letter by letter—the thoughts and phones must naturally express themselves as finger movements, just as the thoughts and phones naturally become mouth and tongue movements when you speak. (Inspired by this post.)
  • Nice keyboards – learn about the various key switch technologies -
  • If you want to find some REAL nerdy keyboard stuff, this forum is the place:

Tuesday, September 14, 2010

Colemak, II

I’ve been typing full-time on Colemak now for a few months and it’s really going quite well. I stumble and make a few typos, but it is continually getting better. I just ran a test and scored 67wpm @ 99.6% accuracy. (That’s an upper end test; I am probably closer to mid-50s on average.) I’m declaring victory.

Sunday, September 05, 2010

ASP.NET MVC No Caching Attribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Application
    /// <summary>
    /// Add this attribute to your Actions and they will have a "Cache-Control: private, max-age=0" header,
    /// ensuring that the responses are not cached by the user's browser. 
    /// </summary>
    public class NoCachingAttribute : ActionFilterAttribute
        public override void OnActionExecuted(ActionExecutedContext filterContext)
            filterContext.HttpContext.Response.CacheControl = "private";

Monday, August 30, 2010

Regular Expressions in SQL 2008 R2

At last! Supported, official regular expression support in SQL Server! It’s a bit of a hack, so I may have to redact the “supported” comment. But here are the fully-documented scripts you get when you install Master Data Services on SQL 2008 R2.

Here’s how to extract them and use them on your own database (only tested on R2, but I suspect any edition of SQL server that supports the CLR would work with these; you will need R2 to install MDS, however):

  • Install MDS from D:\MasterDataServices\x64\1033_ENU
  • Run the Configuration Manager and set up a new MDS database. You will be copying from here and into your own database.
  • Script the Microsoft.MasterDataServices.DataQuality assembly (right click / Script as / Create)
  • Change the AUTHORIZATION to db_datareader
  • Find the functions you need (most under scalar, some under table), and right click, script, create:
  • Delete the USE block, and change the namespace to dbo, or one of your own.
  • Run all of the scripts on your own database, starting with the assembly.

Saturday, August 21, 2010

Tomato & Grape Fresh Chutney

  • Handful of cherry tomatoes, quartered
  • Handful of white sweet grapes, halved
  • Good splash (~1T) of champagne vinegar (other white or rice would work fine)
  • Little olive oil
  • Teaspoon of salt
  • Generous sprinkle of curry powder
  • Generous sprinkle of garam masala
  • A little habanero for bite, finely minced
  • 1 clove garlic, pressed

Mix everything but garlic. Simmer and mush in a pan over medium heat until most of the fruit has separated from the skin. Run through a blender to improve consistency if desired. Return to pan, add garlic, simmer for one minute longer. Serve over pork chops. We loved it.

Space Pen

You know that frustrating feeling when you pick up a pen and it doesn’t write? You scribble and shake it, but it doesn’t do much.

I decided a while ago to try one of those “space pens” to see if its pressurized ink cartridge would solve that problem, and it 100% does. If you want an inexpensive pen that reliably writes the first time, every time, with a continuous, even flow, check these guys out. I went with this model, which fits in my pocket when closed and opens to a comfortable writing size. It’s still just a ballpoint pen and writes like one, but it has a nice weight and balance. All for under $11. Worth every penny.

Fisher Space Pen, X-Mark Bullet Space Pen, Matte Black (SM400BWCBCL)

Tuesday, August 10, 2010

Salmon Marinade and Glaze

  • Soy sauce
  • Maple syrup
  • Lime juice
  • Sriracha chili sauce
  • Finnish Mustard (or medium-sweet brown mustard)

Marinate a chunk of salmon. Baste.

With excess, add a splash of arrowroot or cornstarch, mix well, and then reduce to a molasses consistency. Remove from heat and add a bit of butter.

Thursday, July 15, 2010

How to modify Commerce Server 2009 Web Parts

If you’re running Commerce Server 2009 in SharePoint, you’ve likely wanted to modify an out-of-the-box CS web part. This post will show you a shortcut. The normal way to do this is to open the CS extensibility kit (C:\Program Files\Microsoft Commerce Server 2007\Microsoft Commerce Server 2009\Sdk\Samples\CommerceSharePointExtensibilityKit), resign all of the assemblies with your own SNK, and then update every reference everywhere to be aware of your SNK’s public key token. Here’s a forum post that explains this in more detail. When I tried this I missed some references in config files and the site blew up. If you’re working in a production environment, proceed with caution!

The shortcut is to create a new web part that inherits from the base Commerce Server web part and set the UserControlVirtualPath with your own ASCX (copied from the extensibility kit). This obviously limits your options compared to cracking open the full source, but it is a vastly simpler deploy experience that will allow you to at least customize the markup for your creative team.

Take a look at the screenshots below; there shouldn't be too many surprises. One gotcha to bear in mind is that if your control has a <%@ Register Src="ReadOnlyAddressDetail.ascx" ...> directive, you have to add the dependant ASCX files—the web part won’t render without it, and it doesn’t seem to “know” to fall back to the OOB markup.

Once you deploy the web part, you can add yours in place of the stock Commerce Server one. Piece of cake.


Saturday, July 10, 2010

Home Server Drive Balancer

Check out this great utility for your Windows Home Server, Drive Balancer. It’s designed to rebalance the storage across your pool. It came in handy in my case because I added a new 2TB drive (formerly 4x500GB, now 3x500+1x2TB). I kept waiting for the new drive to start getting files, but that never happened. Then I ripped a Blu Ray and the stupid thing started telling me that there wasn’t enough space to duplicate the new file...grrr...just move some files around and there’s plenty of room!! That’s what this utility does, it solves the literally only gripe I’ve found with this otherwise excellent product.

Be sure to read the readme and walkthrough before you get started. Interestingly, it doesn’t move the files, it just adds blank files in a way that, when triggered by the utility, the built-in file mirroring ends up rebalancing. Definitely add it to your toolkit.

Monday, July 05, 2010

Costa Rica Trip Summary

In February my girlfriend and I went to Costa Rica for a week. I’ve been meaning to write up the trip here to share outside of the pages of my journal...a friend just booked airfare there, so I got motivated. You can see my pictures on Facebook (you’ll need to be my friend).

A goal of ours on this trip was to practice traveling light: one backpack apiece, laundry as we go, and minimal plans. Before landing we only had our car and first & last nights’ hotel booked. The rest we figured out as we went, using our downtime to plan our next move, usually asking the front desk to call the hotel we wanted to stay at for the next night. This helped keep the pace nice and relaxed, even though we were on the move a lot.

Sat 2/20/2010

Flights from ORD to EWR to SJO on United & Continental. Nearly got our itineraries cancelled because of a gate agent’s mistake when we tried to stand by on an earlier flight. They corrected the mistake, but we got lucky that seats were even available on the flight—there were exactly two open seats remaining.

Picked up a diesel 4x4 with a manual transmission from Avis. Opted for the GPS. Would not try to get around without one, as roads are sometimes not well marked. The rental cost was ~$100/wk, so consider buying stateside.

Checked into hotel Cinco Hormigas Rojas (five red ants) in downtown San Jose. Was well after dark in an urban area (see GPS comments above). It’s a cute small hotel, with a “jungle” landscaped into the courtyard that gets visits from birds and bats. The owner Mayra was a sweet lady with a cute pregnant puppy. Each room is uniquely decorated with her own works of art...even the flush handle on the toilet was decorated.

Had dinner at a popular restaurant, Café Mundo, down the street. Simple spaghetti Bolognese was outstanding after a long day of travel.

Sunday 2/21

Drove to Monteverde. 4x4 recommended. Breathtaking views on switchbacking gravel roads up and down (and down and up) mountain after mountain.

Checked into Arco Iris Lodge. A little hidden oasis in a touristy city (a jumping off point for cloud forest trips). Pretty landscaping and a clean, spartan room, fully wood-paneled, with just a bed, a shower+bathroom and a small table. Exactly what we wanted and nothing more, nothing less. We asked of its simplicity, “what more would you need in a hotel?” Which begs the question, “what more do you need in a home?”

Had dinner at Sophia’s, an ex-pat-run place that caters to tourists. A high end meal; we had figs and pork loin, a local cheese quesadilla, ceviche and tres leches for dessert.

Monday 2/22

Woke to (feral?) roosters at 5am. Took an early shuttle to Selvatura for a zip-line adventure in the cloud forest. Had a great time; the guides all spoke excellent English and the whole thing was well orchestrated and inspired confidence—a good thing when you’re flying over the treetops in a harness. I described it as a “Six Flags version of the cloud forest,” and I mean that in a good way. Sure you’d see more wildlife if you weren’t screaming in joy as you soared over the treetops, but you also wouldn’t be screaming in joy. Great experience. Spent seven hours there, including a leisurely walk through the suspension bridges afterwards.

Checked indo El Bosqué lodge (Arco Iris was booked, so we had to go down the road a few km for the next night). The room had a bit of a funky smell to it, but we survived. Had a minor crisis while changing a light bulb that led to broken glass all over the bathroom floor. Had dinner at a brick oven pizza place right next door, Tramonti. It was tasty, but not remarkable.

Tuesday 2/23

Breakfast at Stella’s Bakery across the street. Had gallo pinto (beans, rice and eggs). Good, and sticks with you.

Went on the Monteverde coffee tour. Met Don Francisco, who has lived in the valley for 54 years. He had kind eyes and welcomed us onto his family farm for a tour of his coffee operation. His niece (whose mom is an expat from Wisconsin) acted as translator. Learned plenty about coffee: robusta is illegal in CR to ensure coffee is high quality country-wide, and coffee is almost always planted under fruit trees to provide shade for the plants and food for the families. Great and highly recommended tour if you’re above-interested in coffee.

Drove to La Fortuna, a city at the base of Volcán Arenal. Checked into Cabinas Los Guayabos (guava cabins). This was another gorgeously situated hotel: terra cotta-styled tile throughout, and leading out to the same-tiled patio (emphasizing the oneness of indoors and out), which looked out over the grassy yard, which led to a field with horses in it, which ran up to the base of the most perfectly conically-shaped volcano you can imagine. This whole setting was one of the most beautiful in all my travels, and I still frequently picture it when I think of serene, picturesque settings. But if that volcano blew, we’d be toast. Saw some minor eruptions.

Spent the evening at Eco-Termales, a natural hot spring nearby. Was beautiful and relaxing, with just a handful of other people there (the place down the street, Tobacón I think, had bus after bus out front). We opted to include dinner with the stay there. Good (tilapia & rosemary steak) but unremarkable in every way except one: the black beans. My god, so good I asked for the recipe. The guy said it was made with “summer sauce,” I think? No idea, but it looked and smelled like a tomatillo salsa thing.

That night we decided to change our plans: We had discussed going to Parque Manuel Antonio but wanted to get away from the popular tourist spots. So we went way up north-west, 20km from the border with Nicaragua, on the Pacific.

Wednesday 2/24

Took a horseback ride to La Fortuna Falls with Desafio Adventure Company, where we were able to take a quick dip in the very cold waters. Our guide was knowledgable and spotted animals (a snake, toucans and a tree frog) us city folk trotted right past. We were out and about for 3 hours, and it was just the 3 of us.

Drove 3 hours to Cuajiniquil, Guanacaste. Checked into Santa Elena Lodge. Met the owner, Manuel. This hotel is his family’s home—they live on the first floor and rent out the upstairs. Gorgeous varnished wood paneling throughout. Went to a little restaurant nearby, Soda Bolivar. We had ceviche and a white fish in a garlic butter.

Thursday 2/25

Manuel offered to take us and Nancy & Avery, the only other people in the hotel, on a personal safari in his Land Rover (not the luxury kind, the bare bones not-for-sale in America kind) through Santa Rosa National Park right down the road. We stopped at a few pristine and picturesque beaches in the park. Saw plenty of monkeys (3 species), dozens of birds, and more iguanas than I could count. We had to use a machete to cut through brush that was blocking the road...we definitely put the 4x4 of the Land Rover to use.

My car keys fell out of my pocket somewhere out there in the forest...whoops. Manuel had to call Avis on my behalf to arrange to have a spare set of keys sent up via a bus (we were a good five hour drive away from where the car had been rented).

Had dinner at the seafood restaurant next door to the hotel. The four of us gave Manuel a tip for taking us on the safari—he didn’t want to accept it and so bought us dinner with our money :) Had Pacific lobster tails, followed by some of the best tres leches cake ever.

Friday 2/26

Manuel drove us to the nearest big city, Liberia, to meet the key delivery coming by bus. It wasn’t there...yet, but Manuel made a few calls and got it straightened out. Success. He was a godsend in getting us keys again.

We went to a deserted beach (Jobo beach) and tried to snorkel (using some equipment Manuel loaned us gratis). The surf was too rough, so there was nothing to be seen, save for some puffer fish that were much too close.

We had dinner at that same restaurant next door: filet mignon, and a pesto white fish.

Saturday 2/27

Woke to a flat tire! Wasn’t a problem; the spare was good. We skipped the beach and just took off back to San José. For the first time in my life I tipped a hotel on checkout.

I bought some Vino de Coyol, which is a roadside hooch found in rural areas, made from fermented sap of the coyol palm. It was even sold in a reused 20oz soda bottle. We also picked up a cute brightly-colored piggy bank that is a pretty common souvenir.

We checked into the same hotel that we spent the first night at, and had dinner at the same restaurant. Pizza that we just weren’t in the mood for. Had a nice walk through a bustling shopping area.

Sunday 2/28

Early checkout, morning flight from SJO, connect through IAH to ORD. No troubles!

All in all a great trip. We loved the backpacking feel of it, and planning as you go was exciting and spontaneous. Here’s a map of some highlights:

View Costa Rica Feb 2010 Trip in a larger map

Wednesday, June 16, 2010


I’m slowly learning a new keyboard layout, Colemak. It was invented in around 2005 with the goal of being more efficient than QWERTY and Dvorak, and be easier to learn for QWERTY typists. It keeps ZXCVAQW in the same place for common shortcuts, as well as most punctuation. The hardest part about it is that my fingers can’t keep pace with my thoughts, and that is paralyzing for the writing process! If you’re interested in learning more, visit No special hardware or software is required, just install the layout for your operating system and start training!

Monday, May 10, 2010

Pointing Stick USB Keyboard Roundup Review

Samsung top, center; Lenovo on bottom; Unicomp up topTrackpoint, pointing stick, eraser head mouse, nipple mouse—whatever you call it, if you’re like me and you love it, you don’t want to use a computer without one.

After a chiropractor urged me to stop stooping to look down at my laptop display (which is giving me “military neck,” or a flattening of the curve in the neck), I decided to take my laptop ergonomics more seriously.

First up was raising the laptop display to an appropriate height. I chose the 3M Vertical Notebook Riser (LX550), as it seemed to get the display to the most appropriate height (most competing products raise the body of the laptop at a much shallower angle and/or don't have full freedom of adjustability). While it’s not the most travel-friendly (Logitech’s Notebook Riser wins that award), I chose function over form. Besides, a few reams of paper or a shoebox can serve as a laptop stand in a pinch.

The Keyboards

Now on to the good stuff: USB Keyboards with Pointing sticks. This is a very small product category, and you have to get rid of a lot of your wishes: a natural curve, wireless/bluetooth—none of those products exist with a pointing stick. I found three products meeting my requirements—quite simply, a USB keyboard with a pointing stick:

Samsung, Lenovo and Unicomp, top to bottom
The Samsung Q1: The Bad

Samsung and Lenovo A small and tidy keyboard that even comes with a travel pouch! I was the most excited about this keyboard, and the most disappointed. The keys feel flimsy, the back wasn’t perfectly flat so it wobbled when I typed, and worst of all, the pointing stick just isn’t very good. It has a weird acceleration thing going on, where the center is fairly numb but as you push harder and farther from center, it accelerates non-linearly. Thumbs down for the keyboard, thumbs way down for the mouse.

Other negatives: The WIN key is in the bottom-right, which I can live with. But Home and End require FN modifiers (FN + PgUp = Home), which is a big problem for someone who spends a lot of time in Visual Studio.

The redeeming graces? It’s teeny without feeling teeny. From the left of ‘A’ to the right of ‘;’ it measures 7 1/4”—just 1/4 inch shorter than a regular full-sized keyboard. That and they shave off some more size with narrower Caps Lock, Shift and Enter keys.

If you need an external keyboard occasionally and you need a small & portable model, this keyboard might be for you. But if you’re looking for a full-time keyboard, the Lenovo is still pretty tidy for travel and has a much better feel (plus it’s cheaper). Verdict: not recommended.

Lenovo ThinkVantage ThinkPad USB Keyboard with TrackPoint: The Best All-Around

Best keyboard layout of the group When I unplugged the Samsung and plugged in the Lenovo, I knew I was never going back. The feel of the keys are sturdy. Don’t let the “regular” laptop keyboard look fool you, it’s even better than the keyboard on my Toshiba, as well as my girlfriend’s modern Lenovo laptop. The keys have a buttery softness to them, a firm response, and they’re quiet.

Oh and the pointing stick. It’s perfect. Perfect. Sensitive and responsive, without a dead zone in the center like the Samsung, and it stops on a dime. Perfect.

A lot of reviewers on Amazon have complained that this keyboard suffers from a lag that leads to double-presses or delayed shift-releases. I can say with confidence that the model I got does not suffer from that. I type in the 70 to 90 WPM range, so I’m pretty confident that if the problem existed I’d see it.

If you install the drivers from Lenovo [see footnote 1], you’ll enable the center button+TrackPoint to scroll, plus media keys/volume controls that are very useable.

As for the layout, it’s full-sized (7 1/2” from left of ‘A’ to right of ‘;’), Home and End are actual keys, WIN is in the bottom-left. The only thing is FN is in the far bottom-left corner, where I prefer CTRL, but it’s a minor adjustment that’s well worth it.

Size: it’s slim and sleek. The wrist rest is nice, something I’m used to in a laptop keyboard. It slips into my laptop bag alongside the laptop without any trouble.

Great response, great feel, perfect mouse, acceptably portable, reasonable price: highly recommended—buy now.

Unicomp EnduraPro: The Best to Type On

Lenovo and Unicomp, with their feet extended First a bit of history on Unicomp. They make the only “real” clickety-clackety keyboards, having bought the “buckling spring” patent from IBM/Lexmark some years ago. (Here’s an interesting NPR piece on Unicomp.) Allegedly, buckling spring keyboards are faster than modern “blister” keyboards (referring to the switch underneath the key). These keyboards are supposed to be easier on your hands than modern keyboards, too: when you type on a blister keyboard (including the Lenovo), you don’t get tactile feedback until you push all the way through the key, which is to say, it’s as if you’re hammering away on a hard surface. With a buckling spring, you type until the spring buckles, but not when the movement stops, so it’s gentler. Make sense? And does it live up to the hype?

DSC_5765Without a doubt, it is the best keyboard to type on. The key action is crisp, fast, the keys snap back instantly, and it’s precise. After typing a couple of long-winded emails and much of this review on it, I quickly got over the learning curve of the different “throw” of this type of keyboard over the typical laptop keyboard I’m used to. As promised, the key press registers after about 2mm of pressing, but the bottom of the keywell isn’t for another 1 or 2 mm. Definitely a different and better typing experience than laptop keyboards I’ve grown used to over the past few years.

The pointing stick, however, is another matter. It is on a very long pole, and it’s moderately sensitive. The Lenovo’s pointing stick doesn’t really move, it just senses the pressure you apply to it. The Unicomp’s pointing stick is more like a joystick: you have to wiggle it around and move it in the direction you want. Couple its loose wiggling with a dead zone in the center and only 2 buttons that are hard to click, and it didn’t pass muster. Better than the Samsung, but not in the same league as the Lenovo.

Other notes: top-notch build quality (it weighs nearly 5lbs) and I enjoyed using a full-sized desktop layout, but missed the multimedia keys and volume controls that I quickly found to love in the Lenovo.

Side By Side Typing Speed

I ran through two iterations of this Aesop Fables typing test on each keyboard, in the opposite order the second time, taking the average.

  • (Model): (Min)/(Max) (Average)
  • Samsung: 76/88 82
  • Lenovo: 86/95 90.5
  • Unicomp: 90/95 92.5

While this isn’t a perfect science experiment, it does show that the Unicomp and the Lenovo are fast, topping out for me at 95 WPM. The low initial Lenovo score came because I was used to typing on the Unicomp and switched back to the short-throw laptop-style keyboard and my fingers just didn’t know what to do!

Conclusions and Recommendations

If this review were about keyboards, I’d give the best and fastest typing experience to the Unicomp. But since this review is about pointing stick keyboards, the award goes to the Lenovo. It is a great keyboard, and has a perfect pointing stick. Overall usability goes to the Lenovo, too: with its media keys, middle mouse button with scrolling, and forward & back buttons, it’s the best to use for everyday computing. Typing on it is very good, too, even though it has a traditional (but sturdy) laptop keypress mechanism. If I lived my life on a Bash or Powershell prompt and rarely reached for the pointing stick, I would keep the Unicomp in a heartbeat. Even though I write a lot of code and emails and would benefit from a great typing experience, I really need a great pointing stick to find my way around a modern OS and development tools like Visual Studio.

Maybe someday a perfect keyboard with the right tactile response and the perfect 3-button pointing stick will come to market. Maybe it will even have a gentle ergonomic curve and bluetooth and still be tidy enough to travel with. Maybe someday.

Buy the Lenovo keyboard here at

P.S. This page is full of associate links on Amazon. If you appreciate this review and decide to purchase one of these products from Amazon, please support this site by following the links when you add to your shopping cart.

[1] The drivers install a startup program called skd8855.exe in HKLM\Software\Microsoft\Windows\CurrentVersion\Run that doesn’t seem to do anything. I left ltpPoint because it seems to be responsible for the extra features tab in the Mouse control panel.

Wednesday, May 05, 2010

CryptographicException during SharePoint Configuration Wizard

(Re)installing MOSS 2007 on Server 2008 R2 I got this error:

Calling SPServiceInstance.Provision for instance Microsoft.Office.Excel.Server.ExcelServerSharedWebServiceInstance, service Microsoft.Office.Excel.Server.ExcelServerSharedWebService
Task services has failed with an unknown exception
Exception: System.Security.Cryptography.CryptographicException: Object already exists.

   at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
   at System.Security.Cryptography.Utils._CreateCSP(CspParameters param, Boolean randomKeyContainer, SafeProvHandle& hProv)
   at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
   at Microsoft.SharePoint.Utilities.CertificateManager.CreateSelfSignedSslCertificate(CspParameters parameters, X500DistinguishedName name, DateTime expiresAfter)
   at Microsoft.SharePoint.Administration.SPProvisioningAssistant.ProvisionIisWebSite(String serverComment, String[] serverBindings, String[] secureBindings, AuthenticationMethods authenticationMethods, String[] authenticationProviders, String path, AccessFlags accessFlags, String applicationName, String applicationPoolId, String[] scriptMaps, String sslCertificateSubjectName)
   at Microsoft.SharePoint.Administration.SPMetabaseManager.ProvisionIisWebSite(String serverComment, String[] serverBindings, String[] secureBindings, Int32 authenticationMethods, String[] authenticationProviders, String path, Int32 accessFlags, String applicationName, String applicationPoolId, String[] scriptMaps, String sslCertificateSubjectName)
   at Microsoft.Office.Server.Administration.SharedWebServiceInstance.Synchronize()
   at Microsoft.Office.Excel.Server.ExcelServerSharedWebServiceInstance.Synchronize()
   at Microsoft.Office.Server.Administration.SharedWebServiceInstance.Provision()
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.InstallServiceInstanceInConfigDB(Boolean provisionTheServiceInstanceToo, String serviceInstanceRegistryKeyName, Object sharepointServiceObject)
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.InstallServiceInstances(Boolean provisionTheServiceInstancesToo, String serviceRegistryKeyName, Object sharepointServiceObject)
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.InstallServices(Boolean provisionTheServicesToo)
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.Run()
   at Microsoft.SharePoint.PostSetupConfiguration.TaskThread.ExecuteTask()

This is actually a file permission error. Bring up properties for the folder C:\Users\all users\Microsoft\Crypto\RSA\MachineKeys, Advanced, Auditing tab, add Full Control for Everyone on the local machine for both failures and successes.

Run the configuration wizard again. It will still fail, but now you’ll know which file has the permissions error.

Bring up the Event Viewer, Security log. Compare the timestamp from the log to the failure audit: there’s your file. Correct permissions (probably take ownership and give yourself full control), run the Wizard again, it will succeed (at least for this step).

When you’re done, turn off the file auditing.

Wednesday, April 28, 2010

On Organization

I have spent too much time organizing the wrong parts of my life.

I used to keep my inbox in Outlook immaculate—zero unread items, everything meticulously categorized and filed. But I rarely went back and looked for items by categories of folders, I almost always searched for it. So I stopped. Now I keep a “Recent Unread” folder that is a view on the items still requiring attention that have come in during the last week or so. If it doesn’t make it into an action item by that time, then it falls out of scope, and I don’t have to care.

I used to store my receipts immaculately. Scan them all in, and then shred the paper, giving them proper file names so they’d sort by date. But I never looked back on them. Now I scan them batches every few months, still grouped by debtor, sort of lazily dumped in a folder.

Same with my business reimbursement expenses. They’re almost always PDF attachments on emails (hotels, airfare, etc), and I used to save them off and rename them into a convention. But for what? Now I copy the whole email into a folder by expense period—much less work, and still easily retrievable when the occasional audit comes through.

If I need to look back, yes, it will take a little more effort, but I so rarely look back. It’s worth the net savings to have to work a little harder when I look back than it is to immaculately organize something I’ll so rarely need to take advantage of. That time is better spent elsewhere, like posting on my blog.

What do you over-organize? Where could you shift the time burden to lookup instead of storage, and net time savings?

Wednesday, April 07, 2010

United's IVR

I called United's 1K-only 800 number today from my cell phone. It went like this:

  • (Recorded voice): Hello and thank you for calling United. Is this ...Travis?
  • (Me): Yes
  • (Recorded voice): Is this about your reservation ...Monday April[Location].
  • (Me): Yes
  • (Recorded voice): What is this regarding? [Listed options]
  • (Me): [One of the options]
  • (Recorded voice): Thank you. I'll connect you with an agent to help you with that.
  • A human answered immediately. She helped me quickly and effortlessly.

Phenomenal. I love good service. And never once did I need to enter my member number, a confirmation number, or anything: I just dialed from my phone and it knew.

Tuesday, April 06, 2010

Google Public DNS

I just configured my router to use Google's Public DNS ( and and pass those IPs down to my clients. Allegedly it'll be faster as they proactively cache and have the infrastructure to handle the scale of "the Internet." Worth a test, eh?

Monday, April 05, 2010

My favorite curry recipe



  • 2 tablespoons olive oil
  • 1 medium potato, cut into 1/2" cubes
  • 2 boneless skinless chicken breasts, cut into cubes
  • 1 tablespoon fish sauce
  • 3 cloves garlic, minced
  • 1 small onion, finely chopped
  • 3 tablespoons curry powder
  • 3 tablespoons brown sugar
  • 1 can coconut milk
  • 1 1/2 cup peas
  • 1 roasted red pepper, sliced thinly
  • 1 tablespoon Sriracha chili sauce


  1. In a skillet with olive oil, brown potatoes and set aside.
  2. Season chicken with fish sauce, and brown in the same skillet. Set aside.
  3. Saute garlic until fragrant, followed by onions, curry powder and brown sugar.
  4. Return chicken and potatoes to the skillet, add coconut milk, roasted pepper slices, peas, and chili sauce (you may omit or add more for heat).
  5. Cover and simmer for 15 minutes or until chicken is tender.
  6. Serve with steamed rice.

Monday, March 22, 2010

Ripping and Transcoding Movies

I use MakeMKV to rip DVDs and Blu Rays to an archive format. I typically rip the main video title, the primary audio track, and all subtitles. I rip the videos to \\SERVER\Videos\Incoming, which is a share residing on my Windows Home Server. I have the script below running as a service (using SrvAny.exe and Any Service Installer), although running it as a service is totally optional. The script below watches that Incoming folder and when it finds a new file, it verifies that it's not still being written (that its size doesn't change in 5 seconds), and then it kicks off two transcode jobs using HandBrake, one for an iPhone and one for an archive format.

Once you get this job set up, all you have to do is rip your movie into \\SERVER\Videos\Incoming\[MOVIE NAME]\title00.mkv and the transcodes will be dumped into \\SERVER\Videos\Movies\[MOVIE NAME]\iPhone.m4v and Archive.mp4. In other words, one-click transcoding.

Write-Output ("Setting process priority to Idle."); [System.Diagnostics.Process]::GetCurrentProcess().PriorityClass = [System.Diagnostics.ProcessPriorityClass]::Idle; $incomingDir = "\\SERVER\Videos\incoming"; # Loop forever while(1) { $mkvs = get-childitem $incomingDir -recurse -filter *.mkv; if(!($mkvs)) { Write-Output ("No file found."); } else { # Force into an array if only one element found if(!($mkvs.Count)) { $mkvs = ,$mkvs; } Write-Output ("Found $($mkvs.Count) files"); foreach($mkv in $mkvs) { Write-Output ("Processing $($mkv.Directory.Name)"); #if($mkv.Directory.Name -notmatch "There Will Be Blood") #{ # continue; #} Write-Output ("Checking to see if file is still being written..."); $info1 = Get-Item $mkv.FullName; start-sleep 5; $info2 = Get-Item $mkv.FullName; Write-Output ("."); if($info1.Length -ne $info2.Length) { Write-Output ("Skipping!"); continue; } $outputDir = "\\SERVER\Videos\movies\$($mkv.Directory.Name)"; $outputFilePrefix = "\\SERVER\Videos\movies\$($mkv.Directory.Name)\$($mkv.Directory.Name)"; if(!(test-path $outputDir)) { mkdir $outputDir; } # Kick off two transcode jobs $psI = [Diagnostics.Process]::Start("C:\Program Files\Handbrake\HandBrakeCLI.exe", "-i ""$($mkv.FullName)"" -t 1 -o ""$outputFilePrefix - iPhone.m4v"" -f mp4 -X 480 -e x264 -q 20 -a 1 -E faac -6 dpl2 -R 48 -B 128 -D 0.0 --markers=""C:\Documents and Settings\Administrator\Local Settings\Temp\2\iPhone-1-chapters.csv"" -x cabac=0:ref=2:me=umh:bframes=0:subq=6:8x8dct=0:trellis=0:weightb=0 -v 1"); #2>"$outputFilePrefix - iPhone - Error.txt" > "$outputFilePrefix - iPhone.txt"; $psA = [Diagnostics.Process]::Start("C:\Program Files\Handbrake\HandBrakeCLI.exe", "-i ""$($mkv.FullName)"" -t 1 -o ""$outputFilePrefix - Archive.mkv"" -f mkv --strict-anamorphic -e x264 -q 20 -a 1 -E ac3 -6 auto -R Auto -B 32 -D 0 --markers=""C:\Documents and Settings\Administrator\Local Settings\Temp\2\archive-1-chapters.csv"" -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v"); #$psI = & "C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "$($mkv.FullName)" -t 1 -o "$outputFilePrefix - iPhone.m4v" -f mp4 -X 480 -e x264 -q 20 -a 1 -E faac -6 dpl2 -R 48 -B 128 -D 0.0 --markers="C:\Documents and Settings\Administrator\Local Settings\Temp\2\iPhone-1-chapters.csv" -x cabac=0:ref=2:me=umh:bframes=0:subq=6:8x8dct=0:trellis=0:weightb=0 -v 1 2>"$outputFilePrefix - iPhone - Error.txt" > "$outputFilePrefix - iPhone.txt" #$psA = & "C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "$($mkv.FullName)" -t 1 -o "$outputFilePrefix - Archive.mkv" -f mkv --strict-anamorphic -e x264 -q 20 -a 1 -E ac3 -6 auto -R Auto -B 32 -D 0 --markers="C:\Documents and Settings\Administrator\Local Settings\Temp\2\archive-1-chapters.csv" -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v 2>&1 #> "$outputFilePrefix - Archive.txt" $psI.WaitForExit(); $psA.WaitForExit(); mv $mkv.FullName "$outputFilePrefix - Original.mkv"; if($psI) { #echo "in it"; #$psI.WaitForExit(); #Wait-Process -InputObject $psI; #Wait-Process -InputObject $psA; #mv $mkv.FullName "$outputFilePrefix - Original.mkv"; } else { #Write-Output ("Error processing $($mkv.Directory.Name)"); } #break; } } # Wait one minute, and then try again. start-sleep 60; }

Saturday, March 13, 2010

Thursday, March 11, 2010

How to access the Targeting Context from within a Commerce Server Basket Pipeline

I fixed a bug yesterday where an order-level discount targeted against Targeting Context.Subtotal had an incorrect value—it was set in code before running the basket pipeline, but the subtotal was inaccurate before running the pipeline (newly added items to the basket had a price of zero prior to the pipeline execution, for example).

The solution was to update the subtotal in the targeting context during pipeline execution, after fetching the latest pricing data from the catalog and before running the OrderDiscount pipeline component. Here’s the code to get at the targeting context from within a pipeline:

public int Execute(object pdispOrder, object pdispContext, int lFlags)
    IDictionary context = (IDictionary)pdispContext;
    Decimal subtotal = (decimal)((Microsoft.CommerceServer.Interop.Profiles.IProfileObject)context["ContextProfile"]).Fields["Subtotal"].Value;

Thursday, March 04, 2010

Marinated Swordfish

Adapted from.

3 Tbsp lime juice
2 tsp rice vinegar
2.5 Tbsp olive oil
1 tsp salt
1/4 tsp fresh ground black pepper
1 tsp fresh grated ginger
3 or 4 fresh basil leaves, chopped
1/4 tsp fresh thyme leaves
1/4 fresh jalapeño, minced (seeds optional if you prefer spicier)
3/4 lbs swordfish

Whisk together all ingredients (except fish) in as small a pan as possible to hold the fish. Cover and marinate 2 to 3 hours, turning once. Broil or grill to desired doneness (130 to 140°F internal temperature).

Monday, February 08, 2010

Saag Something-or-other

This is my first attempt at a Saag Paneer. Except I didn't follow a saag paneer recipie; instead I loosely followed this Saag Aloo recipie. So it’s a curried spinach and paneer recipe. Next variation I want to add some cream, yogurt, coconut milk, or sour cream to the mix for a creamy texture.

2 medium Yukon Gold potatoes, cut into 3/4” cubes
9 oz fresh baby spinach leaves, tough stems removed
1 medium onion, diced (or 5 shallots)
1 Tbsp butter
1 jalapeño pepper, seeds removed, minced (optionally add back the seeds for a spicier dish)
1 clove pressed garlic
1” ginger root, peeled and minced
1 1/2 Tbsp curry powder
2 Tbsp brown sugar
8 oz paneer cut into 3/4” cubes (could substitute cooked chicken or tofu, or omit entirely)
7 oz canned chopped tomatoes
1 tsp salt, or to taste

In a large pot, bring a 2 quarts water to boil. Parboil the potatoes until starting to soften, 7 to 10 minutes. Remove potatoes from boiling water and put in cold water to stop the cooking; keep the boiling water hot.

Add the spinach leaves to the boiling water for two minutes to wilt. Remove from water and smoosh between paper towels on a plate to remove most of the water. Fold the spinach out of the paper towels and onto a cutting board. Chop until fine.

Add the butter, onions, potatoes and salt to a hot skillet and sauté. After 5 minutes, add the paneer. Continue sautéing until onions are translucent and the potatoes turn golden brown, about 7 minutes. Add the garlic, ginger, jalapeño, curry powder and brown sugar; stir until fragrant and well mixed, about 1 or 2 minutes.

Add tomatoes, combine well, and serve with naan or over rice. Serves 4.

Tuesday, January 26, 2010

Announcing ePubLib

I have published a project on CodePlex, ePubLib. ePub is quickly becoming the defacto standard for e readers, and after getting my hands on a (used and cheap) Sony Pocket Reader I wanted to be able to create documents to put on the device.

The format isn't particularly complicated, but there are a lot of little things that have to line up. This library makes it extremely easy. Create a Book object. Create 1 or more Chapter objects. Add the Chapter to Book.Chapters. Call Book.Save(). You can do the same thing for images as of the commit last night. The only knowledge that's required is basic XHTML skills and .NET to use the library.

I also wrote a utility to log me into The Economist's web site (I'm a paying subscriber) and scrape the Print Edition. It works great, a proper TOC, all of the articles and all of the images. I don't think I can upload that source to CodePlex due to perceived copyright concerns, but drop me a comment if you're interested.