Thursday, January 26, 2006

Dangerous Biking

IMHO, the most dangerous time to be biking is in heavy traffic.

It seems counterintuitive since cars are mostly stopped or moving very slowly at that time. But frustrated drivers make snap decisions and quickly cut in and out of lanes or decide at the last second to take that back road home. This is the most dangerous time for a biker because you are generally the last thing they are thinking about anyways.

In traffic also look out for side streets opening up on your right. Polite drivers leave gaps so that drivers going the opposite way can turn through the traffic. They are making a left hand turn. On a bike you are virtually invisible to the turning driver and are at risk. The only thing to do is to slow down and make sure that no one is making that turn.

Monday, January 23, 2006

Superbowl!!!

Seattle is going to the super bowl finally!!! After years of SeaHawking it they finally made it. This is going to be a great town for the next 2 weeks.

It would have been great to make it to the actual game. I went there with the hope that I might be able to find 2 tickets floating around for a not quite insane price. No such luck. I was there an hour before kickoff and in that whole time I only saw 2 tickets for sale. Guess that's what happens when your team hasn't been to the superbowl ... ever.

Not all lost though. Instead my wife and I bar hopped around the stadium and saw the game amongst throngs of fans. Great experience.

Thursday, January 19, 2006

Conspiracy Theory Debunked: WMF Flaw was a backdoor

The recent WMF flaw gained a lot of media attention due to severity of the bug. Most of the stories detailed the attack and the risks to users. Steve Gibson took it one step further and claimed this was an intentional back door made by Microsoft.

This theory has now been thoroughly debunked by Mark Russinovich of SysInternals. Check out the article.

http://www.sysinternals.com/blog/2006/01/inside-wmf-backdoor.html

Tuesday, January 17, 2006

One drought ends and another begins

On Saturday the Seahawks won their first post season game in 20 years. Despite early efforts to Seahawk the game, Hasslebak pulled out the game. Next weekend it's Carolina!

On Sunday our days of consectutive rain streak came to an end at 27. But no worries it started raining again today.

Saturday, January 14, 2006

Registering a MshSnapIn with LUA

The new Beta 3 version of Monad introduces the idea of a single shell. Instead of being forced to create a new shell to host all of your CmdLet's you can load them into the current running shell. This is done via the concept of MshSnapIn's.

MshSnapIn's are a way of identifying, grouping and providing a common install. Snap ins are installed by a common utility called InstallUtil that comes with the .NET Framework. By default the installer writes the snap in information under HKLM:\software\Microsoft\MSH\1\MshSnapIns thus preventing LUA users from registering snap ins.

By modifing the permissions on that key slightly you can enable a normal user to register MSH snapins. Here a MSH method to do so.

function UpdateSnapInPermissions
{
[string]$ident = "{0}\{1}" -f ${env:\userdomain}, ${env:\username};
$rights = [Enum]::Parse([System.Security.AccessControl.RegistryRights], "CreateSubKey,QueryValues,SetValue");
$allow = [Enum]::Parse([System.Security.AccessControl.AccessControlType], "Allow");
$rule = new-object System.Security.AccessControl.RegistryAccessRule $ident,$rights,$allow;
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("software\microsoft\msh\1\MshSnapIns", $true);

# Add the rule to the collection
$col = $key.GetAccessControl();
$col.AddAccessRule($rule);
$key.SetAccessControl($col);
$key.Close();
}

Friday, January 13, 2006

Day 26

Today is the 26th straight day of rain in Seattle. We're now just one week shy of the all time record of 33 days. Truthfully I didn't even realize that we were on any kind of streak. From January till about March it's at the very best overcast every day. I just figured this was part of the normal swing of things. Maybe I need to get out more

http://seattletimes.nwsource.com/html/...

Thursday, January 12, 2006

Smoking Chain Lube

I dropped by REI this afternoo to pick up some lubrication for my bike. The back derailer was annoying me this morning. While reading the back of the cans I noticed an interesting warning on one of them.

DO NOT SMOKE

The first thought I came up with was "How on earth do you smoke chain lube"? This was soon followed by several other along the lines of "why would you ever ...".

It occurred to be about 5 minutes later that they really intended for it to mean "Do not smoke ... around the chain lube." Seems like the better warning would be the more complete one. For what if some wonder started pondering the question of how to smoke chain lube and lit up a cigarette for thought?

Wednesday, January 11, 2006

MSH having a specific profile for every machine.

I like to have my profile scripts do custom actions for specific computers and as such I have a profile script on every computer at home/work. They are not always in the same location or drive. My home directory at home is a shared drive and mounted via Active Directory. So Monad loads up the same profile script no matter what computer I am on (the one in my shared home drive). I would like to configure it on a computer-by-computer basis to load up from a different location.


Monad will load your profile from a set of predefined locations but it does not allow you to specify where before hand. The solution I've used to get around this is to have my shared Monad script call into my Machine specific script.


Since this is Monad I've of course scripted this solution. Below is the script




# Read in the information about known computers
function ReadComputerMap
{
[string]$file = combine-path $(parse-path -parent $profile) "Computers.txt";[hashtable]$map = @{};
foreach ( $line in get-content $file)
{
if ( $line -match "(?[a-z_0-9\\-]+)\|(?[a-z_\\:]+)" )
{
$map[$Matches["name"]] = $Matches["path"];
}
}
return $map;}

# Write out the computer map passed infunction
WriteComputerMap([hashtable]$map)
{
[string]$file = combine-path $(parse-path -parent $profile) "Computers.txt";
echo "# Generated File (do not edit)" > $file;
foreach ( $name in $map.Keys )
{
$line = "{0}|{1}" -f $name, $map[$name];
echo $line >> $file;
}
}

$newPath = $args[0]
$sfPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
$targetDirPath = "{0}\msh" -f (get-property $sfPath Personal).Personal
$targetPath = combine-path $targetDirPath "Microsoft.Management.Automation.msh_profile.msh";

if ( -not (test-path $targetDirPath) ) { mkdir $targetDirPath > $null }

# Make sure we've visited this computer before and that the profile has
# not been moved
[hashtable]$map = ReadComputerMap;
[string]$compName = "{0}\{1}" -f ${env:\userdomain}, ${env:\computername};
if ( -not ($map.ContainsKey($compName)) -or $newPath -notlike $map[$compName])
{
$map[$compName] = $winconfig;
WriteComputerMap $map;
}

echo "# Generated File (do not edit!!!)" > $targetPath;
echo "switch (`"`${env:\userdomain}\`${env:\computername}`")" >> $targetPath
echo "{" >> $targetPath;
foreach ( $name in $map.Keys )
{
$line = "`"{0}`" {{ . '{1}';break}}" -f $name,$map[$name];
echo $line >> $targetPath;
}

echo "default { echo `"Unknown computer`" }" >> $targetPath;
echo "}" >> $targetPath;
}

Monday, January 09, 2006

NewsAggregator for NNTP and RSS

I've been searching for a good news aggregator that combines RSS and NNTP into one UI. I've tried out a lot of different services over the last month. I'm not even 100% set on free. If there was a good enough reader out there I could be talked into paying a little bit of money for it (~$50).


But I've finally found a winner, Omea. The reader version is free and can do RSS and NNTP. It's a great interface and typically has a low memory impact on the system. You can do pretty much everything you want including


  • Minimize to the system tray

  • Add notifications to specific threads

  • Different signatures for each news server (finally!!!)

One of my more favorite features is it's ability to filter based on different sets of data. For instance it's very easy and fast to find articles posted that day, 3 days ago, by that user, etc...

There are a couple of minor downsides. The first being that the UI is a little bit unintuitive when you first start using it. After an hour though it's great.

The second is true of almost any non-web based RSS reader. Each machine maintains it's own read/not-read list. So when I go home after work all of the posts I have already read are marked as unread again at home. Omea is extendable though so I'm considering trying to write an add-in that will keep a an already read list in a centralized location of sorts. We'll see if I ever get around to it.

Jared.net

Another Jared has setup a website www.jared.net where other jared's can post links to their web sites. It's quite funny.

Sunday, January 08, 2006

Marshaling an array of data

This falls under the category of methods I wish had been added to some of the BCL classes but weren't. When working with Win32 API calls you often end up with a pointer that contains an array of data you want to get access to. Here's a generic method for getting that array.


public static class MarshalHelper
{
internal static T[] PtrToArray<T>(IntPtr ptr, int count)
where T : struct
{
IntPtr current = ptr;
T[] array = new T[count];

for (int i = 0; i < count; i++)
{
array[i] = MarshalHelper.PtrToStructure<T>(current);
current = new IntPtr(current.ToInt32() + Marshal.SizeOf(typeof(T)));
}

return array;
}
}
}

On the other hand I can understand why they didn't add this method. The line that contains "current.ToInt32()" isn't entirely correct on 64 bit systems. It should be ToInt64 instead. But what impact will that have on a 32 bit system. Probably be minutely slower.


What is going to be really neat is when the next version of the c# compiler comes out with Method Extenders. Without any changes to the CLR we will have the ability to add methods to pre-existing classes. That way I can make my MarshalHelper class into a true extender of System.Runtime.InteropServices.Marshal. Then calling my method becomes "Marshal.PtrToArray(myPtr, 3)".

Saturday, January 07, 2006

Generic Wishlist for new version of C#

IMHO, Generics are one of the best parts of C# v2.0. Lots of redundant brain dead code can be eliminated by making generic version.

Generic constraints are also a beautiful invention but they fall painfully short in one area, the new constraint. The new constraint is limited in that you can only specify that a type has an empty accessible constructor. My want is that you can specify the types that are a part of that constructor like so.


public class Foo
{
public static T CreationHelper(int value)
where T : class, new(int)
{
// Some setup code followed by
return new T(int);
}
}

The key is the code that could go before and after the new. Logging code can be inserted or if you're dealing with memory, management code can be inserted. I tend to encounter the want for this feature when I am doing interop code.

Friday, January 06, 2006

Biking to work again

It's great to be biking to work again. During the later part of November and pretty much all of December, Seattle had quite a cold spell. So cold it essetnially prevented me from biking to and from work. I had to resort to weekend rides in the afternoon when it was somewhat warmer than the mornings and evenings.

Essentially all I asked for for Christmas was warm biking gear. My favorite and most useful piece was a Windproof N2S jersey from Gore-Wear. Incredibly useful for cold and somewhat rainy weather.

Once I got back from vacation with family I rode to work on my first day back. Glorious, if a bit more difficult than it was the last time I rode. Except on the way back I popped one of my tires. Popped the tire so bad in fact that I ended up being forced to replace it. But I have my new tires on now and am thoroughly enjoying riding to work in the morning again.

Now I just have to deal with the rainy season up here.

Thursday, January 05, 2006

Great site on String.Format rules in .NET

Check SteveX's great site on how to specify the format of information in a String.Format request.


http://blog.stevex.net/index.php/string-formatting-in-csharp/

Wednesday, January 04, 2006

Interfaces are not contracts

One part of OO programming that I have little agreement with is the idea that interfaces are contracts. The only thing that an interface specfies is how to call the particular method. However it makes no gaurantees whatsover as to what the method does. Every implementation of an interface could do a separate and totally unrelated action.

My favorite example of this are properties/methods that expose file names. A lot of interfaces (or just properties on abstract/parent classes) have a property that exposes information about an underlying or related file. Typically this is called FileName and is a string.

But what does that really mean? Is it the


  • The name of the actual file: foo.txt

  • The full path of the file in normal notation: c:\bar\foo.txt

  • The relative path of the file: bar\foo.txt

  • The full path of the file in URI format: file://c:/bar/foo.txt

I've played with interfaces where different implementations have returned any number of the above. It's quite frustrating.

But it goes to the point that interfaces by themselves are not contracts.

Tuesday, January 03, 2006

.NET and runtime side-by-side

Having 2 versions of the same dll loaded inside the same process is supported by the CLR but it doesn't come for free. Check out this article by Junfeng

http://blogs.gotdotnet.com/junfeng/archive/2005/05/25/421661.aspx

Monday, January 02, 2006

Getting the text of a window in .NET

I see this request come up often in CodeProject and on MS newsgroups. How can you get the text of a non-managed window. The easiest way is to go through the P/Invoke layer. Here's a sample.



public class Foo
{
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern uint GetWindowText(
IntPtr hwnd,
StringBuilder builder,
int maxCount);

public static string GetWindowText(IntPtr hwnd)
{
StringBuilder builder = new StringBuilder(256);
if ( 0 == GetWindowText(hwnd, builder, 256) )
{
throw new Exception("Error getting window text");
}
return builder.ToString();
}
}



There is one entry of note here. In the DllImport statement I set the CharSet to CharSet.Auto. The problem here is that the default is CharSet.Ansi which is not correct for most operating systems which run in Unicode. Whenever you're going to the OS layer through P/Invoke set this to CharSet.Auto.

Christmas Photos

Uploaded the photos to Flickr from my trip back home for Christmas. (http://www.flickr.com/photos/jaredparsons/sets/1717793/). Flickr is definately one of the cooler online photo album tools that I've dealt with. If you haven't tried it out yet I would certainly recomend it.