January 2007 - Posts - Jon Galloway

January 2007 - Posts

[Code] Show a file in Explorer

I've noticed that some of my favorite programs have options to open the currently selected file in Explorer. I don't just mean that they open the right folder, but that they preselect the right file for you.

Visual Studio 2005 does it when you select "Open Containing Folder in the File tabs:

Firefox has it in the downloaded file dialog, and TimeSnapper shows it as an option in image browse mode.

It's not hard to add to your programs, too:

Open File In Explorer

The code's reasonably simple once you've got the right arguments to pass to Explorer:

private static void ShowFileInExplorer(string filePath)
{
if (!File.Exists(filePath))
throw new FileNotFoundException("File not found", filePath);
ProcessStartInfo processStartInfo
= new ProcessStartInfo();
processStartInfo.FileName
= "explorer";
processStartInfo.UseShellExecute
= true;
processStartInfo.WindowStyle
= ProcessWindowStyle.Normal;
processStartInfo.Arguments
=
string.Format("/e,/select,\"{0}\"", filePath);
Process.Start(processStartInfo);
}

Google Personalized Homepage (IG) - Read a post inline

Google IG FeedsI've been using the Google personalized homepage for a while as a simple "heads up display". 

I run RSS Bandit on my laptop; it's too tempting of a distraction to run on my main work computer. I've got the Google homepage set up with my top feeds, plus e-mail and news, and I glance at it during the day to see if something interesting's going on that can't wait until I can spend some quality RSS time.

A cool new feature showed up on my Google homepage yesterday - inline views of RSS posts. The headlines (post titles) all show up as they always did, but clicking the + icon expands the post out so I can give it a quick skim. Neat!

Of course, there's the potential problem that it's more distracting now, but I think I'll actually be less likely to switch over to my laptop (with all 1000+ feeds vying for my attention) if I can just skim a quick post and get back to work.

Why not Live.com?

Since I mostly write about Microsoft technologies, I bet I'll get a comment asking why I use the Google homepage over Live.com's.

I've stuck with the Google homepage mainly because I use GMail, and I haven't found a good Live.com gadget that shows my Gmail inbox. There's one out there that kind of works, but it's basically running in a frame and it feels kludgy. I'm not bagging on the developer of that gadget; I actually wrote one a while ago, but I wasn't happy enough with it to release it.

The difficulty is due to the Live.com web gadget model, which hosts your gadget but requires you to do your own requests via XMLHttp. That's a problem if you want to read content from an HTTPS resource, since browser security prevents permission elevation by requesting an HTTPS resource from an HTTP page. I'm not sure about this, since I've never built a Google desktop widget, but I believe Google's model proxies the requests. That means that Google's servers are doing the web requests and merging all the content into a page they deliver to you, rather than delivering you a page that hosts a bunch of independent "pagelets" which make their own requests from each browser.

Getting Cropper to work in Vista

UPDATE: A new version of Cropper with these changes has been released. Grab it here: http://blogs.geekdojo.net/brian/articles/Cropper.aspx

Summary

Cropper is my favorite screenshot utility, mainly because of the plugin support. It's not really usable in Vista because the graphics compositing changes in Vista cause problems with just BLT'ing from the desktop DC so the Cropper form is included in the captures. It's not simple, but you can decompile it, add 4 lines of code, and have a version of Cropper that works in Vista. There's talk of a new version of Cropper, but until then this will let you run Cropper 1.8 on Vista.

Confessions of a screenshot freak

I'm really into screenshot programs. I use them daily while writing a book, writing documentation, writing blog posts, and even OCR'ing screenshots of code. I regularly use several screenshot applications: WinSnap, the Vista Snipping Tool, TimeSnapper (not really a screenshot program; it's a desktop recorder), and Cropper.

Cropper is my favorite program, because it supports plugins like "Send to Flickr". (I've written a few myself, including a few I'm waiting to release until an official Vista version comes out).

The problem

Vista's window compositing system is radically new. I'm not going to pretend that I'm an expert on what's changed, but I do know that copying the desktop image (BitBlt from the Desktop HDC) has changed. The net result is that Cropper's translucent form shows up in the captured images (this image should be completely blank):

CropperCapture[100]

A cheesy solution

Step 1 - Decompile Cropper.exe

Cropper was originally distributed with the source, but for some reason the source hasn't been included with recent versions. It's not obfuscated, though, so you you can get the source in seconds with Reflector and Denis Bauer's File Disassembler plugin.

Step 2 - Modify TransparentCropForm.cs as follows:

 

private void TakeScreenShot(ScreenShotBounds bounds)
{
bool _currentlyVisibile = base.Visible;
this.highlight = true;
base.PaintLayeredWindow();
try
{
base.Hide();
switch (bounds)
{
case ScreenShotBounds.Rectangle:
if (this.isThumbnailed)
{
this.imageCapture.Capture(this.VisibleClientRectangle, this.maxThumbSize);
return;
}
break;

case ScreenShotBounds.ActiveForm:
this.imageCapture.CaptureForegroundForm();
return;

case ScreenShotBounds.FullScreen:
this.imageCapture.CaptureDesktop();
return;

case ScreenShotBounds.Window:
this.imageCapture.CaptureWindowAtPoint(Cursor.Position);
return;

default:
return;
}
this.imageCapture.Capture(this.VisibleClientRectangle);
}
catch (InvalidOperationException exception1)
{
TransparentCropForm.ShowError(exception1.Message,
"Error Taking Screenshot");
return;
}
finally
{
if(_currentlyVisibile)
base.Show();
this.highlight = false;
base.PaintLayeredWindow();
}
}

Only 4 lines were added:

bool _currentyVisible = base.Visible;
base.Hide();
if(_currentlyVisible)
 base.Show();

There are more elegant solutions, but they require changes to a lot more files and require passing references to user interface objects deep into the core DLL's. This solution is good enough for govm't work.

Step 3 - Recompile

This actually turned out to be the hardest part, since for some reason File Decompiler's csproj file had the resource references all confused. If you run into problems, contact me and I can send you my Cropper Vista Ghetto Build.

Posted by Jon Galloway | 1 comment(s)
Filed under: , ,

Identicons - Ported from Java Servlet to HttpHandler

Summary

Identicons provide a nice visual indicator that's unique to each user on a website. It's unique since it's based on the user's IP, but it's not possible to recover the IP by looking at an Identicon so each user's privacy is protected.

Identicons look cool. Phil implemented it in the comments on his blog:

Any comments I post on Phil's site will have that little pink symbol, while Matt (an anonymous user) will always get that purple design. That's a nice visual cue, but it also prevents me from pretending to be Matt and writing stupid comments. Yes, unfortunately, stuff like that happens.

Backstory

Things move fast in thissy here bloggersphere.

Don Parks came up with the identicon idea on 1/18, and Jeff Atwood wrote me about it on the evening of 1/20. My obsessive coding compulsion kicked in, and I ported it form a Java servlet to an ASP.NET HTTP Handler and got it to compile. I called it quits at 2 AM and passed it to Jeff, who spent his Sunday debugging a tricky GDI conversion issue (plus cleaning up the code and adding cache optimizations). I was calling Graphics.RotateTransform(turn * 90, MatrixOrder.Append), but that MatrixOrder.Append was causing each of the nine tiles on the identicon to overwrite the previous, so all you saw was the last written.

Monday morning, Phil repackaged Jeff's implementation as a compiled DLL + handler file so it will work in ASP.NET Web Application Projects.

Phil and Jeff have already written nice posts on how it works, so I thought I'd just talk about moving this from Java to .NET land.

Porting a Java servlet to an HTTP Handler with the JCLA

I used the JLCA - the free Java Language Conversion Assistant. If you've got Visual Studio 2005 installed, there's a good chance you've got the JLCA on your computer, living a lonely life in in C:\Program Files\Microsoft Visual Studio 8\JavaLanguageConversionAssistant. It's a command line utility, but it's not too hard to use. The command I used was:

jconvert "c:\users\jon\documents\identicon_-_2_java_src" /out "c:\projects\identicon"

That works out to jconvert (source folder) /out (destination folder). Not too tricky.

The JLCA creates an HTML conversion report (IE only) in the root of the target folder with all the warnings and errors. I'm glad I didn't spend much time with it, because all the information was copied into the source as comments.

At that point, it was time to apply the age old programming technique known as BOIUIW (bang on it until it works). Some highlights:

  1. First, convert the servlet to an HTTP handler. The best plan there is to just create a new handler and copy the code from the servlet's doGet() method to the handler's ProcessRequest() method.
  2. Comment out or convert calls to the servlet's log and cfg methods to .NET equivalents.
  3. Replace calls to the SupportClass methods (created by the JCLA) anywhere they caused a problem. They help to get things close to compiling, but in some cases it was simpler to just replace them with the .NET equivalents. As an example, JCLA created SupportClass.MessageDigestSupport, which I replaced with System.Security.Cryptography.SHA1CryptoServiceProvider.
  4. Slightly interesting - the Java code used sbyte[], but the .NET SHA1 message dictionary hash provider creates a byte[]. You can convert from a byte[] to an sbyte[] by first casting to an Array object: sbyte[] hashedIp = (sbyte[])(Array)hashedIpBytes;
Posted by Jon Galloway | 1 comment(s)
Filed under: ,

Code Puzzle #2 - Generate random fake surnames - Recap

Code Puzzle #2 posed the following task: Write a simple function which generates fake but passable surnames (read more here). As I'd hoped, I got several great submissions with a range of interesting approaches. I'd like to say that we're all winners, but the rules were clear: "This is a fixed contest; my solution will win first place."

Finally, here's my solution. It's the ugliest solution by far, but I was pretty happy with the output. I divided the consonants into four groups:

  • common - can appear anywhere, and appear frequently
  • average - can appear anywhere, and appear with... um... average frequency
  • middle - slightly lower frequency, and not allowed to start a name
  • rare - appear rarely, but are allowed to start a name

I seeded the random number generator with Guid.NewGuid().GetHashCode(), per Brendan Tompkins' tip. System.Random bases its randomization based on a seed. If you pass the same seed in every time, you get the sequence out every time. If you don't seed the Random Number Generator, it uses the system clock (Ticks, to be precise). The problem is that if you call it multiple times in a tight loop, you'll get the same values out. Seeding based on a GUID hashcode ensures a random (though not evenly distributed) sequence.

You'll notice that my letter arrays contain duplicates of some values - common letters like A,E,S, and T are repeated multiple times. That's a cheap trick to allow for a random output that weights some values more highly.

I added common prefixes and suffixes after looking at the common surname list, then tweaked the weightings so they'd show up at the right frequency.

 

private static string GenerateSurname()
{
string name = string.Empty;
string[] currentConsonant;
string[] vowels = "a,a,a,a,a,e,e,e,e,e,e,e,e,e,e,e,i,i,i,o,o,o,u,y,ee,ee,ea,ea,ey,eau,eigh,oa,oo,ou,ough,ay".Split(',');
string[] commonConsonants = "s,s,s,s,t,t,t,t,t,n,n,r,l,d,sm,sl,sh,sh,th,th,th".Split(',');
string[] averageConsonants = "sh,sh,st,st,b,c,f,g,h,k,l,m,p,p,ph,wh".Split(',');
string[] middleConsonants = "x,ss,ss,ch,ch,ck,ck,dd,kn,rt,gh,mm,nd,nd,nn,pp,ps,tt,ff,rr,rk,mp,ll".Split(','); //Can't start
string[] rareConsonants = "j,j,j,v,v,w,w,w,z,qu,qu".Split(',');
Random rng
= new Random(Guid.NewGuid().GetHashCode()); //http://codebetter.com/blogs/59496.aspx
int[] lengthArray = new int[] { 2, 2, 2, 2, 2, 2, 3, 3, 3, 4 }; //Favor shorter names but allow longer ones
int length = lengthArray[rng.Next(lengthArray.Length)];
for (int i = 0; i < length; i++)
{
int letterType = rng.Next(1000);
if (letterType < 775) currentConsonant = commonConsonants;
else if (letterType < 875 && i > 0) currentConsonant = middleConsonants;
else if (letterType < 985) currentConsonant = averageConsonants;
else currentConsonant = rareConsonants;
name
+= currentConsonant[rng.Next(currentConsonant.Length)];
name
+= vowels[rng.Next(vowels.Length)];
if (name.Length > 4 && rng.Next(1000) < 800) break; //Getting long, must roll to save
if (name.Length > 6 && rng.Next(1000) < 950) break; //Really long, roll again to save
if (name.Length > 7) break; //Probably ridiculous, stop building and add ending
}
int endingType = rng.Next(1000);
if (name.Length > 6)
endingType
-= (name.Length * 25); //Don't add long endings if already long
else
endingType
+= (name.Length * 10); //Favor long endings if short
if (endingType < 400) { } // Ends with vowel
else if (endingType < 775) name += commonConsonants[rng.Next(commonConsonants.Length)];
else if (endingType < 825) name += averageConsonants[rng.Next(averageConsonants.Length)];
else if (endingType < 840) name += "ski";
else if (endingType < 860) name += "son";
else if (Regex.IsMatch(name, "(.+)(ay|e|ee|ea|oo)$") || name.Length < 5)
{
name
= "Mc" + name.Substring(0, 1).ToUpper() + name.Substring(1);
return name;
}
else name += "ez";
name
= name.Substring(0, 1).ToUpper() + name.Substring(1); //Capitalize first letter
return name;
}

Please feel free to submit your solution. We've only covered a few ethnicities here, there are plenty more to cover.

Posted by Jon Galloway | 1 comment(s)
Filed under: ,

Code Puzzle #2 - Generate random fake surnames

I'm talking to you, Mr. Thymmet! Step forward and be counted, Ms. Betusen! It's time for another Code Puzzle! My solution will be posted on Friday, 1/12. Get to work!

UPDATE: Read the recap here

Task: Write a single function which generates fake but passable surnames.

How does it go back together again?Rules / Notes:

  • Post your solution in the comments along with 25 results.
  • Names should be pronouncable and passable as real surnames. If you saw them on a business card, your reaction should at the most be an inward chuckle.
  • Your solution should be capable of generating a large number of random names. (My solution generated 1.7+ million distinct names in a simple test.)
  • My solution creates surnames which would make sense in the US. Feel free to write something target different ethnicities, but please let us know which you're targeting.
  • Keep it simple. My solution is 33 lines and 2,700 characters, including some comments. My function takes no parameters and returns a string.
  • Use whatever language you want; please specify if it's not VB.NET or C# using .NET 2.0. Yeah, I know you can probably write this in 8 characters in PowerShell, Ruby, Python, and Boo. So do it!
  • Your code cannot reference any external resouces (no internet access, no file or data access, etc.).
  • Your code doesn't need to worry about filtering obscenities (but please keep your obscene results to yourself).

Judging criteria:

This is a fixed contest; my solution will win first place. However, to achieve glory in this contest you must:

  • Generate passable surnames
  • Use concise yet readable code
  • Try to be elegant, but things like magic numbers and hardcoded strings are fine by me

Sample output:

for (int i = 0; i < 50; i++)
Console.WriteLine(GenerateSurname());

Greta
Slease
Sloje
Seethoson
Sleeslo
Tethe
Heshoez
Lackesm
Sorommees
McTeame
Louwheth
Sheysset
Sakneesm
Lathet
Tosoatesm
Betusen
McTasea
Fata
Thymmet
Degha
Thateyez
Thethatea
McShatte
Tethes

(Yes, these look silly when listed together. The idea is that they shouldn't stand out on a page in the phonebook. Let's see you do better!)

References:

UPDATE: Is this for spammers?
No. I was working on a sample application and wanted to generate a few hundred names to demonstrate paging through data. I thought about it, and I don't believe this will help spammers. It's very easy for spammers to just use lists of actual names (such as the common surnames list in the references above). Spam filtering algorithms can't block e-mail from common surnames, or they'd be blocking most of their legitimate e-mail traffic. It would be a waste of time for spammers to bother with generating random surnames.
Posted by Jon Galloway | 1 comment(s)
Filed under: ,

Five things you didn't know about me

I tend to keep things down to business on my blog, but after having been tagged three times I decided go with this "Five Things" meme. I'd been planning to write a Hello World thing for my 500th post anyhow. Here goes:

I won the Showcase on The Price Is Right

ABrandNewCarSome friends had extra tickets and invited my brother and me to see The Price Is Right back in 1992. I was one of the last people in line to make it in, and was sitting on a folding chair in the back row (reading a book, truth be told) when they called my name. I didn't know how the show worked at all - I started to run up on stage.

The first step is the Contestant's Row, where you have to be the closest bidder without going over the actual price. I goofed up on the first item by bidding one dollar under the highest bid. Not smart at all. I bid one dollar more than the highest bid on the second item, an armoire (which is sitting in our bedroom right now).

I then had another game where I had to pick a price between two items - an oven and a sofa. The game as called Magic Number, and idea is that the contestant moves a lever up and down on this machine to set the price. I had no clue, but the people we'd come with had said to listen to the audience if we weren't sure. I just moved the lever up and down until people were clapping a lot ($1050), and won the oven and sofa.

Next up was the Showcase Showdown, in which you spin a big wheel and try to get closest to $1.00 without going over. I tied another contestant at $0.65 and had to choose between spinning again or having a "spin-off" in which we both got to spin once. I went with the odds and won the spin-off.

I passed on the first Showcase, which included an expensive designer ball gown and some muscle car. I was glad I did - the next showcase had a Saturn SL2. Saturn was one of the first carmakers to go with fixed prices, and I'd just been looking at Saturns a few months earlier so I knew the price. I still had to guess on the other items (a bar set and a jukebox), but it was a lot easier. I annoyed Bob and the audience by adding all the prices up (out loud, a little too slow for TV, and - most funny - my addition was a little off). But I won The Showcase.

The video of the show is up on YouTube:

I was a submarine officer

JonJeffersonCityI (and my four brothers) went to the Naval Academy in Annapolis. I graduated in 1992 and spend the next 5 years in the submarine service. All officers on an attack submarine (with the exception of the supply officer) are nuclear power trained, so before reporting to the submarine I spent six months at Nuclear Power School in Orlando and another six months qualifying as an Engineering Officer of the Watch on the A1W prototype in Idaho Falls. During this time I learned that there's a huge difference between nuclear science and nuclear engineering. I'm really good at figuring out how things work, but I'm slow (compared to most of the engineers I worked with) at applying them. I was in the top 10% of my class at Annapolis with a B.S. in Physics, but I barely passed Nuclear Power School and Prototype.

Then I spent the next 4 years on the USS Jefferson City, a Los Angeles (688i) class submarine. Junior officers on a submarine rotate through a lot of jobs, so during that time I was in charge of (in turn) the following divisions: Fire Control, Torpedo, Machinery, Reactor Controls, and Communications.

Submarine officers also stand watch, which is in addition to their management duties as a division officer. I stood the following watches:

  • Junior Officer of the Deck - This watch doesn't require qualifications, so it's what you do when you first report to the ship. The main thing I remember about it was spending hours looking out the periscope. It sounds neat, and it is... for the first 5 minutes. After that, it's just murder on your eyes (imagine looking through a microscope for hours).
  • Engineering Officer Of The Watch - In my early twenties, I was supervising seven enlisted nuclear plant operators for six hour shifts. Unlike most nuclear power plants, submarine power plants are constantly changing power and running drills, so it was a very busy job. I can still remember the dread while waiting for the drills to start as an EOOW for the nuclear safety exams the ship had to pass once a year.
  • Officer of the Deck - Driving the boat. While OOD's work for the Captain and follow charts prepared by the Navigator, the OOD is commanding the ship. I was giving orders to (and responsible for) 140 people and a billion dollars worth of machinery (a nuclear reactor, missiles, torpedos, high voltage electronics, high pressure hydraulics, etc.) several hundred feet underwater. Sheesh.

The majority of the time my schedule was 6 hours on, 12 hours off. That 12 hours off wasn't really off, it was often filled up by division officer duties, training, drills, junior officer collateral duties, and occasionally some sleep. There were stretches where I was 6 on 6 off, and for a while I was 12 on 6 off. Sleep is a overrated.

We did two West Pac deployments while I was on board. It was a nice time to be in the Navy, since the cold war was basically over and the US wasn't yet involved in Iraq. We made our own excitement, though:

  • We scraped bottom once, going fast and deep. A few feet deeper (literally) and we could have been in real trouble. The captain lost his job over that one.
  • While anchored off Thailand, we got wrapped up in another US ship's anchor and had to be cut loose by divers
  • Flooding in the fan room!
  • Probably loads of other stuff I've forgotten...
  • (none of the above was my fault. honest!)

I met my wife when our bands toured the U.S together

JonSoulJunkI played in my brother's band, Soul-Junk, from 1994 to 2001. We toured the country a few times, did a European tour, and played at a bunch of festivals (North By Northwest, South By Southwest, CMJ in New York City, etc.). We played at The Knitting Factory in NYC one time. My brother Glen is an incredible musician. He's since started a company that does music for TV commercials; they've done some Superbowl ads.

I first learned HTML to run our band's website.

I met my wife, Rachel, on our first U.S. tour right after I got out of the Navy in 1997. That tour almost killed me. We bought a used RV that appeared to be in much better shape than it actually was. The brakes went out (overheated, it turns out) while we were driving down a steep road, the whole drive shaft dropped out after I'd driven all night from Rochester to Rhode Island, we had tires blow out, etc.

I hardly noticed, though. I was in love with the pretty girl in the band we were touring with. Rachel sang (and still often sings) with The Danielson Famile. We were engaged four months later. Time flies, we're now expecting our third daughter.

Rachel and I are competent musicians, but we were both pretty much along for the ride. I got to meet a lot of bands backstage, like Low, Sonic Youth, and Blonde Redhead. My wife sewed a jacket for the son of one of the guys in The Flaming Lips.

I used to hang out a little with Sufjan Stevens before he blew up into a teen idol. He's a good friend of Rachel's family. He played drums on one of our EP's, and we spent a little while talking about recording digital audio while on a short tour together. He had me remix one of his songs as a pre-release extra for his last album, Illinois.

There's a full length movie out now about The Danielson Famile. It includes some interesting background about the close relationship between The Danielson Famile and Sufjan Stevens.

I played bass and a lot of electronics - keys, effects, drum machines, etc. I got into computer music production and engineered a bunch of our songs on a 166MHz machine with 48MB of RAM; it crashed constantly. I wrote a live drum machine program in VB6 and got to perform with it a few times (including shows at the Knitting Factory NYC and at a museum in Paris). I've kept up with digital audio technology since then, and have been amazed at the progress. I used to have to use a calculator to figure out things like note lengths and delay settings; now tools like Acid and dbGlitch can instantly do things that took me hours of painstaking (but enjoyable) work.

I'm a coffee geek

CIMG0617I've got a ridiculous number of coffee preparation methods at my disposal for a non-barista. Here are the methods I've used in the past few months:

  • Capresso Super-automatic Espresso Machine
  • Starbucks Vacuum Pot
  • Stovetop Moka Pot
  • Coffee Press
  • Aeropress
  • Turkish Ibik

This past year I've gotten into roasting my own coffee beans ghetto style, in an electric popcorn popper. I've been wanting to write a post about coffee but haven't made the time for it.I don't really drink a lot of coffee - maybe a few cups a day. I just want them to be really good cups!

I'm writing a book

I'm writing a book for SitePoint with Phil Haack and Jeff Atwood. It's a cookbook style ASP.NET book for their popular Anthology series, which works well a group of first time book authors with a background in writing for weblogs. I'm really enjoying it and hope to do a lot more writing in the years to come.

Okay, who to tag...

How about Roiy Zysman, Eric Willis, Ben GriswoldKeith Rull, and Scott Galloway.

Posted by Jon Galloway | 13 comment(s)
Filed under:
More Posts