Check out my new blog at

Thursday, July 31, 2008

On Traveling

I have been cooped up in a small town for almost two years.  When I started working for Microsoft I was (and still am, by the way) really looking forward to traveling.  In the past thirty days, I have been to Houston, New York City, Seattle, and I am scheduled to return to Seattle shortly.


Be careful what you wish for.  Haha.  Actually, I am thrilled to be out and about but I have noticed some changes over the years.  Ten years ago, when I worked for Microsoft as the Technical Product Manager for Microsoft Project, I traveled so much I spent the following ten years depleting my United Airlines frequent flyer miles on upgrades.  I had something like 178,000 miles racked up over just two years.   Those were the days.

It seems the biggest change is the mood in the airport.  Obviously the security context has changed dramatically after 911 and the cost of fuel has really done a number on the airline industry.  The net effect is that people don't appear as happy to travel.  I take issue with this because we are so blessed in this country--and the world really--when it comes to airline travel.  For most of human history, just traveling to the next village or town was a major ordeal.  Today, traveling to another hemisphere is both affordable and feasible for many, many more people than at any other time in history.

To travel is to celebrate our connectedness as a world.

That being said, taking a flight is a bit like being digested by a large animal.  You know your ultimate destination (and hopefully you come out feeling a bit better than that which comes out of an animal after a large meal).  You know the basic route.  You know that in spite of your frustrations and occasional delay, you really can't do anything about your situation until you come out the other end. 

My advice is this: go with the flow.  Learn to enjoy traveling again.  The security measures are there to protect.  The airlines are doing their best in a crippling situation.  The airports are really like malls with decent (albeit expensive) food and the people watching can't be beat.  Talk to a stranger.  Learn about why others are traveling.  And first and foremost, don't take this freedom for granted.  For most of the world, traveling for the first time on an airplane would be likely perceived as a life changing event if not straight up magic.

The one thing I miss is happy flight attendants.   I get why they are stressed out--jobs are on the line, crazy passengers, security threats, not enough time at home, and the litany goes on.  I go out of my way to thank these people for their work because I can imagine that what sounded glamorous--and may even was at one time--has turned into a stressful grind.

Oh, I have to go.  My flight is boarding.  One last note:  Thanks to Sky Dayton for Boingo!

Thursday, July 24, 2008

Back to my Roots

This coming Monday I will once again don the Blue Badge...I am going back to work for Microsoft.   Over ten years has passed since I walked the halls of Building 18 & 25 in Redmond.  I was just a kid back then and yet Microsoft gave me such opportunities and challenges.  I feel very much like I am returning to my roots.  My first job at Microsoft was answering the telephone at Product Support Services--no, I didn't actually solve problems; I simply collected names and addresses before forwarding the caller to an engineer.  Much later (at least it felt that way), I was doing software engineering for Microsoft on a contract basis.  In between, I worked as a procurement officer buying hardware for various groups in Redmond.  Microsoft was my family when I was growing up--guys like Paul and Larry McDaniel, Ken Inglis, Garin Pangburn, Glenn Minch, Jeff Smith, David Jenkins, and Neil Charney were right there with me as I worked hard to learn the craft.

I grew up and moved on to other opportunities beyond One Microsoft Way--and in the process I was sometimes critical of Microsoft (what child doesn't rebel?).   People like Scott Fuller, Eric Gioia, John Gioia, Donna Fitzgerald, Jim Tisch, Brian Kennemer, and Kobe Connor, and others schooled me in business, marketing, and software development.  I learned a great deal from these people.

Later, I joined another family--The International Institute for Learning.  I am a very lucky man.  I am leaving a group of people that I love and respect to start another adventure.  LaVerne Johnson, Steve Osborn, Susan Palermo, Judy Umlas,  Zack Halbrecht, and others taught me more about the craft and even more about life.  There is no way I could ever repay what IIL gave me and my family.  Never.

I realize this post is sappy but that is why I must write.  I am so thankful to all of those that helped me before in ways that can never be measured (John, Eric, LaVerne and Steve).  Thank you.

I am so thrilled to be part of a new and great team.  Many of them I know from a previous life and many are new to my life.  On balance, I get the best of both worlds:  I have a great new adventure and plenty of friends that share in our previous success.

The last and most important thing is this:  I thank my wife for being totally on my side every step of the way.  Go Team Africa.

Wednesday, July 23, 2008

Microsoft Singularity

I got Microsoft's experimental operating system up and running.  Singularity is mostly (and I mean MOSTLY) written in managed code.  Cool stuff.  There is a Research Development Kit available on CodePlex.  I was able to hook windbg to the kernel and step through some very interesting code.


Tuesday, July 22, 2008

Mapping Assignments Between a 2003 Task and a 2007 Task with mpFx

   1: private void CreateAssignments(Guid projectGuid,
   2:                                     Task legacyTask,
   3:                                     Guid taskGuid,
   4:                                     ref ProjectDataSet projectDataSet)
   5:      {
   6:          foreach (Microsoft.Office.Interop.MSProject.Resource legacyResource in legacyTask.Resources)
   7:          {
   8:              Guid resourceGuid = _resourceMap[legacyResource.Name];
  10:              // If the resource is not part of the project team, we have to update it
  11:              if (!_projectTeams[projectGuid].Contains(resourceGuid))
  12:              {
  13:                  OnAnalyzeStatusChanged(this, string.Format("Adding {0} to the proejct team", legacyResource.Name));
  14:                  using (ProjectTeamDataSet projectTeam = _projectServer.Projects.OpenProjectTeam(projectGuid))
  15:                  {
  16:                      ProjectTeamDataSet.ProjectTeamRow resource = projectTeam.ProjectTeam.NewProjectTeamRow();
  18:                      resource.PROJ_UID = projectGuid;
  19:                      resource.RES_IS_ENTERPRISE_RESOURCE = true;
  20:                      resource.RES_NAME = legacyResource.Name;
  21:                      resource.RES_UID = resourceGuid;
  22:                      resource.NEW_RES_UID = resourceGuid;
  23:                      resource.RES_TYPE = (int) Resource.Type.WorkResource;
  25:                      projectTeam.ProjectTeam.AddProjectTeamRow(resource);
  27:                      _projectServer.Projects.UpdateProjectTeam(projectGuid, projectTeam, _checkedOutProjects[projectGuid].SessionGuid, false);
  29:                      _projectTeams[projectGuid].Add(resourceGuid);
  30:                  }
  31:              }
  33:              ProjectDataSet.AssignmentRow assignment = projectDataSet.Assignment.NewAssignmentRow();
  35:              assignment.PROJ_UID = projectGuid;
  36:              assignment.TASK_UID = taskGuid;
  37:              assignment.ASSN_UID = Guid.NewGuid();
  38:              assignment.RES_UID = resourceGuid;
  40:              projectDataSet.Assignment.AddAssignmentRow(assignment);
  41:          }
  42:      }v

Monday, July 21, 2008

Keeping it Fun!

``I think that it's extraordinarily important that we in computer science keep fun in computing. When it started out, it was an awful lot of fun. Of course, the paying customers got shafted every now and then, and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful, error-free perfect use of these machines. I don't think we are. I think we're responsible for stretching them, setting them off in new directions, and keeping fun in the house. I hope the field of computer science never loses its sense of fun. Above all, I hope we don't become missionaries. Don't feel as if you're Bible salesmen. The world has too many of those already. What you know about computing other people will learn. Don't feel as if the key to successful computing is only in your hands. What's in your hands, I think and hope, is intelligence: the ability to see the machine as more than when you were first led up to it, that you can make it more.''

Alan J. Perlis (April 1, 1922-February 7, 1990)

MIT, "Dedication." Structure and Interpretation of Computer Programs. 1999. MIT Press. 21 July 2008

Also, check out Epigrams on Programming, also by Perlis:

Friday, July 18, 2008

.Net (2.0) Connection String Manager: Find and Replace Connection Strings Across an Entire System

I am working on project composed of a couple WinForms applications, a series of console applications, two Windows services, and a web site.  Each system component talks to the same application database plus the web site talks to an ASPState database.  As I am wrapping this project up, I need to setup the system to work against different configurations (essentially a development server, a staging server, and a production environment). 

I needed a simple way to sweep across the entire system and modify connection string information, plus change the ASPState database to point to the correct server, depending on configuration.  I haven't written any code for a while because I am working primarily on documentation these days... I got a bit of a coding itch this morning.   So, I spent a few hours writing a tool that does a smart find and replace of connection string information across the entire system.


Here is the code that handles setting the connection strings in a Windows executable (in some cases, there are up to TEN connection strings because I am overriding connection string information in other assemblies--see an early post about that problem).

   1: private void RepaceInAppConfig(string configFile)
   2: {
   3:     Configuration configuration = ConfigurationManager.OpenExeConfiguration(configFile);
   5:     ConnectionStringsSection configSection = 
   6:                             (ConnectionStringsSection) configuration.GetSection("connectionStrings");
   8:     for (int i = configSection.ConnectionStrings.Count - 1; i >= 0; i--)
   9:     {
  10:         ConnectionStringSettings connection = new ConnectionStringSettings(configSection.ConnectionStrings[i].Name, connectionStringTextBox.Text)
  11:                                               {
  12:                                                   ProviderName = configSection.ConnectionStrings[i].ProviderName
  13:                                               };
  15:         configSection.ConnectionStrings.RemoveAt(i);
  17:         configSection.ConnectionStrings.Add(connection);
  18:     }
  20:     configuration.Save(ConfigurationSaveMode.Minimal, true);
  21: }
  22: v

Here is the code that handles replacing the connection strings in a web.config.  Keep in mind that I cannot use the ConfigurationManager stuff here because I am not opening the web.config from the site--the OpenWebConfiguration requires a virtual path...

   1: private void ReplaceInWebConfig(string configFile)
   2: {
   3:     XmlDocument xmlDocument = new XmlDocument();
   5:     xmlDocument.Load(configFile);
   7:     XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
   8:     xmlNamespaceManager.AddNamespace("ns", "");
  10:     if (defaultStringsCheckBox.Checked)
  11:     {
  12:         ReplaceWebConfigConnectionStrings(xmlDocument, xmlNamespaceManager);
  13:     }
  15:     if (stateStringsCheckBox.Checked)
  16:     {
  17:         ReplaceWebConfigStateConnectionInfo(xmlDocument, xmlNamespaceManager);
  18:     }
  20:     xmlDocument.Save(configFile);
  21: }
  23: private void ReplaceWebConfigStateConnectionInfo(XmlDocument xmlDocument,
  24:                                                  XmlNamespaceManager xmlNamespaceManager)
  25: {
  26:     XmlNode sessionStateNode = xmlDocument.SelectSingleNode("//ns:system.web/ns:sessionState", xmlNamespaceManager);
  28:     XmlAttribute sessionStateConnectionAttribute = sessionStateNode.Attributes["sqlConnectionString"];
  30:     if (sessionStateConnectionAttribute != null)
  31:     {
  32:         if (stateDatabaseTextBox.Text.Equals("ASPState", StringComparison.InvariantCultureIgnoreCase))
  33:         {
  34:             sessionStateConnectionAttribute.Value = string.Format("data source={0};trusted_connection=true", stateServerTextBox.Text);
  36:             if (sessionStateNode.Attributes["allowCustomSqlDatabase"] != null)
  37:             {
  38:                 sessionStateNode.Attributes.Remove(sessionStateNode.Attributes["allowCustomSqlDatabase"]);
  39:             }
  40:         }
  41:         else
  42:         {
  43:             if (sessionStateNode.Attributes["allowCustomSqlDatabase"] == null)
  44:             {
  45:                 XmlAttribute customSqlDbAttribute = xmlDocument.CreateAttribute("allowCustomSqlDatabase");
  47:                 customSqlDbAttribute.Value = "true";
  49:                 sessionStateNode.Attributes.Append(customSqlDbAttribute);
  50:             }
  52:             sessionStateConnectionAttribute.Value = string.Format("data source={0};initial catalog={1};trusted_connection=true", stateServerTextBox.Text, stateDatabaseTextBox.Text);
  53:         }
  54:     }
  55: }
  57: private void ReplaceWebConfigConnectionStrings(XmlDocument xmlDocument,
  58:                                                XmlNamespaceManager xmlNamespaceManager)
  59: {
  60:     XmlNodeList connectionStrings = xmlDocument.SelectNodes("//ns:connectionStrings/ns:add", xmlNamespaceManager);
  62:     if (connectionStrings != null && connectionStrings.Count > 0)
  63:     {
  64:         foreach (XmlNode node in connectionStrings)
  65:         {
  66:             if (node.Name.Equals("add", StringComparison.InvariantCultureIgnoreCase) && node.Attributes["connectionString"] != null)
  67:             {
  68:                 node.Attributes["connectionString"].Value = connectionStringTextBox.Text;
  69:             }
  70:         }
  71:     }
  72: }v

As you can see from the number of checkboxes in the options groupbox, there are plenty of ways to configure the search criteria to just what I needed.

So, this thing works and now I can switch to another configuration without rebuilding the system (there are ways to automate setting connection strings in the build process through Nant or MSBuild).

Have a great weekend

Wednesday, July 16, 2008

Microsoft Project Fx (mpFx) - Update

mpFx is certainly not a dead project--I have just been too busy working on another project.  I have collected quite a bit of feedback from folks who are interested in the project.  Much of that feedback will make it into the next experimental build.  Unfortunately, due to other projects, I am unable to put a timeline on it.

Stayed tuned and thanks for your patience!

Wednesday, July 09, 2008

Blogging from New York City

Manhattan is a slightly rough diamond set in a sea of humankind...I love this place.

I lived here for a couple of years and enjoyed every second of it.  The work, the people, the diversity, the pace, the prices (well, maybe not that)--plus my wife and I spent our first year together in Manhattan and learned to live happily in 218 square feet.  We cleaned our apartment to a New York shine in about 14 minutes. 

Those days are long gone, what with two kids and a real house with a back yard, but our memories still cause us both to go completely silent when we see Manhattan in a movie or a book.  The smells of the city bring back so many images and feelings from that time. 


The picture to the left is a shot looking down Broadway from W 53rd, towards Time Square.  My wife and I loved to walk the city.  Our Block Buster store is on 8th and 51st, a few blocks from where this shot was taken.  We used to walk down 48th or lower on the way to get a video so we could walk through the Time Square area, just to take it all in.  We love movies and must have taken this walk more than 200 times during that year.  Here is a shot of our Block Buster.


It is a funny thing about walking in Manhattan.   You can tell those who have lived here for a while from the tourists simply by how they navigate through streets.  It is hard not to gawk at the sites when you live in New York City, but you learn to walk at the a pace that I have yet to experience in the cities I have lived in or by (Los Angeles, Portland, Seattle, Washington DC, and Albuquerque).  It is FAST.   And exactly right for what goes on in New York.  The tourists bunch up and stand there looking around like they just can't believe people actually live here.  Well, we did.

There are some 30,000 restaurants in New York and yet everybody who lives here seems to have their local favorite.  Ours happened to be exactly 12 feet from the entrance to our building.  Our building, by the way, is located at Lexington and 50th, kitty-corner to the Waldorf and across the street from the W Hotel in Midtown.  There is no way to describe what living there was like because there are at least seven hotels within a two block radius.  imageHere is a shot of the awning of our favorite diner.  You can just see beyond the sign a green awning.  That is the entrance to our old building.   I popped in there today to see if our doorman still worked there and behold!  Alan Jackson is the greatest doorman in Midtown.  We miss him.

Being in Manhattan and being so in love with my wife was the greatest gift.  So many people are less fortunate and never get to see a city live New York, let alone live there.  We are thankful for our time in this beautiful place. 


Content on this site is provided "AS IS" with no warranties and confers no rights. Additionally, all content on this site is my own personal opinion and does not represent my employer's view in any way.