# Monday, November 30, 2009

Episode 63

In this conversation, independent consultant Michael Eaton describes the challenges developers face estimating software projects. He then describes approaches to these challenges, based on his experience.

Monday, November 30, 2009 3:27:37 AM (GMT Standard Time, UTC+00:00)
# Thursday, November 26, 2009

Sometimes, life gets hard and it's easy to forget that I have much for which to be thankful. Here are some things for which I am thankful this year.

My sons
At 15 and 18, they have grown up strong and smart and good natured (at least they are good-natured by teenager standards). They are tall, good-looking, athletic and popular, without being arrogant about it. I cannot wait for them to fully grow to manhood.

My siblings
My sister passed away this year. Her death and what followed put a major strain on the whole family. My siblings and I banded together for support, without which we could not have made it through this trying time.

My parents
They are pushing 80 and their health varies each day, but they are still going strong. I'm glad they are still a part of my life.

My friends
You know who you are and I appreciate the listening ear and the cold beer.

My career
This wasn't my first career choice, but it is the one that I've enjoyed the most. The constant learning keeps me moving forward.

Happy Thanksgiving all. Don't forget the good things and good people in your life.

Thursday, November 26, 2009 4:19:25 PM (GMT Standard Time, UTC+00:00)
# Tuesday, November 24, 2009

Recently, I was asked to migrate code from one source control repository to another.  The customer had been using Visual Source Safe (VSS) for many years and had dozens (maybe hundreds) of projects checked in. Most of these projects had a long history of file versions.
VSS was a decent product when it was first released, but it falls far short of newer source control systems, such as Team Foundation Server (TFS), Subversion and CVS. This customer selected TFS as their new source control system, but they did not want to lose the history they had captured in VSS.

They asked me how to move the years of VSS history into TFS. Tools exist to do this, including  Microsoft’s VSS2TeamFoundation (available at  http://msdn.microsoft.com/en-us/library/ms181247(VS.80).aspx). However, migration tools have several disadvantages:

  1. Migrating years of source control can take a really long time, maybe weeks. You will probably want to do a test migration of your data, which will extend the time requirement even further.
  2. If you have been checking code into a source control system for any length of time, there are bound to be some mistakes: Projects that were started but never went anywhere; Code changes that were mistakenly checked in and had to be reverted; and duplicate source code erroneously checked into two distinct folders. If you migrate your all source code history, these mistakes will be migrated as well.

A simpler alternative to migrating every version of every project in every folder is to simply get the latest code from the old source control repository and check it into the new repository. Using Visual Studio, this requires only a few steps:

  1. Open the project in Visual Studio
  2. Get latest from the old source control system
  3. Remove bindings to the old source control system
  4. Connect to the new source control system
  5. Check the code into the new source control system

Repeat this for each solution. You will now have a current version of all relevant code checked you’re your new source control system.

Some users will tell you this is not enough. These users want to keep all the history of every bit of code - every version, every branch and every project. Using the above migration strategy, you can still do that. My recommendation is to keep the history in your old repository, mark that repository as read-only and leave it online. Users will still be able to use this old source control system to find their old code, but will use the new source control system for all version control going forward. This is far simpler and faster than trying to push years of changes into a new repository.

The lesson here is: Always consider the simplest alternative and determine whether it meets your needs, before considering more complex solutions.

Tuesday, November 24, 2009 11:49:04 AM (GMT Standard Time, UTC+00:00)
# Monday, November 23, 2009

Episode 62

In this episode, Jay Harris discusses the challenges integration code from different team members and how Continuous Integration can help solve these challenges.

Monday, November 23, 2009 11:46:40 AM (GMT Standard Time, UTC+00:00)
# Wednesday, November 18, 2009

Episode 61

Chris Woodruff organized the 2009 Grand Rapids Give Camp which helped dozens of charities with software projects. On the final day of the Give Camp, Chris sat down with us to describe what went into the camp and what was accomplished.

Wednesday, November 18, 2009 6:25:04 AM (GMT Standard Time, UTC+00:00)
# Tuesday, November 17, 2009

By any measure, this past weekend's Grand Rapids Give Camp was a big success.

Over 70 volunteers worked at the Grand Rapids YMCA to build software projects for dozens of charities. Most of the volunteers were technical people - Developers, Database Administrators and Designers - but some came to assist with the logistics. In additions, local companies provided food, drink, facilities, giveaways.

Projects ranged from new web sites to automated contact management systems. Chris Woodruff, who coordinated the event was impressed with the quality of the work he saw. "We have such a great technical community, so (getting volunteers) was the easiest part," said Woodruff. When it was all over, the charity representatives were happy and several declared that the delivery exceeded their expectations.

Speaking commitments and family emergencies have kept me from fully engaging in past Give Camps, so this was the first one in which I contributed the entire weekend. My team created a web site for the Kent County 4-H Council, which they can easily update without hiring a technical resource. You can see the site at http://kentcounty4hcouncil.com/.

Woodruff is already thinking about next year's event, which will likely be held in July on the same weekend as a similar event in ann arbor.

More photos

Tuesday, November 17, 2009 12:40:01 PM (GMT Standard Time, UTC+00:00)
# Wednesday, November 4, 2009

IMG_7945 The October 2009 Great Lakes Area .Net User Group featured Sogeti principal consultant Jesse Murray speaking about The SharePoint, a talk that was originally titled "SharePoint - The Right Way". For many in the audience, this was a first look at developing solutions in SharePoint and the challenges of this development. Here is a recording of that presentation.

 
Wednesday, November 4, 2009 12:58:01 AM (GMT Standard Time, UTC+00:00)
# Monday, November 2, 2009

Episode 60

Stephen Toub, lead Program Manager on the Microsoft Parallel Computing Platform team, sat down with us to discuss the reasons why parallel computing is important, the challenges in writing code to take advantage of multiple cores, and what Microsoft is doing to make it easier for developers to write this code.


Links:

Parallel Computing Developer Center

Parallel Programming with .NET

Monday, November 2, 2009 11:52:30 AM (GMT Standard Time, UTC+00:00)
# Sunday, November 1, 2009

Back To Basics

I remember how excited I was in the early days of .Net when I discovered how easy it was to write a Windows Service. I probably wrote a half dozen services that first year. But I hadn't written one in years and (oddly) hadn't even heard anyone talking about writing a Windows service in as long.

Perhaps the reason one hears so little about Windows Services is because the way we write them has changed so little since .Net 1.0.

A Windows Service is not dependent on a particular user being logged in. In fact, a Windows Service can run if no one is currently logged onto the machine on which it is running. This makes a Windows Service inherently more secure than a Windows Forms application or a Console application because you can run it on a server, set credentials and log out of the console.

To create a Windows Service, open Visual Studio and select File | New Project. In the Project Types tree of the New Project dialog, expand either Visual C# or Visual Basic node and select the Windows node. In the Templates area of the dialog, select Windows Service. Set the Name, Location and Solution as you would any other project and click OK to create the project.

By default, a Windows service contains one class named "Service1". The name of this class isn't really important because it isn't called externally, so I always leave this default name. If you double-click this class in the Solution Explorer, it opens in a Design view. Select View | Code to switch to a code view of the class. Notice that the class inherits from ServiceBase and that it contains overrides of two methods: OnStart and OnStop.

As you might guess, OnStart contains code that runs when a service starts and OnStop contains code that runs when a service stops. I put setup code into OnStart, such as initializing variables that my service will need. I generally put very little code in the OnStop method, but this is where cleanup code goes.

Services are designed for long-running processes and are meant to stay in memory for a long time -sometimes months or years. Most of the services I've written use a timer object to periodically wake up and perform some check and respond if that check finds something. For example, you might check the contents of a folder every 10 minutes and, if an XML file is found in that folder, move it to a new location and parse it appropriately.

For example I  recently wanted a program that would check an error log every few minutes and automatically attempt to correct any errors found there. I had already written a class to read the error log, retry each error found and remove from the log any errors that were retried successfully. So my service only needed to call this class every 5 minutes. I used a timer class to do this. A partial code listing is shown below.

protected override void OnStart(string[] args)
{
    // Every 30 seconds, a timer will do some work
    timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
    timer1.Interval = 30000; 
    timer1.Enabled = true;
    timer1.Start();

}

protected override void OnStop()
{
    timer1.Enabled = false;
}

private void timer1_Elapsed(object sender, EventArgs e)
{
    // Wake up and perform some action.
    // [Cpde omitted]
}

I prefer to keep the code in the service to a minimum and abstract complex logic to a separate assembly. This makes testing and debugging easier. So the omitted code in the above example would call out to another assembly to do the hard work.

Installing a Service
In order to install a service, you will need to add an Installer class. Select Project | Add New Item; then select the Installer Class template. This class also opens in the designer by default. Select View | Code to see the code. The Installer class inherits from Installer, but you don't need to override any methods.

You can set some attributes of the service to make it easier to find. The Installer class's constructor is the place to do this. Instantiate a new ServiceInstaller and ServiceProcessInstaller, set properties of these objects, and add these objects to the Installer Class to affect the Windows Service when it is installed. Common properties that I like to set are

Class Property Description of property
ServiceInstaller ServiceInstallerServiceName The name of the service. This must match the ServiceName specified in WindowsService1.
ServiceInstaller DisplayName A name displayed in the Services Manager applet.
ServiceInstaller Description A description displayed in the Services Manager applet
ServiceProcessInstaller Account A built-in account under which the service will run.
ServiceProcessInstaller Username The name of the user account under which the service will run.
ServiceProcessInstaller Password The password of the user account under which the service will run.

For the ServiceProcessInstaller, you will set either the Account property or the UserName and Password properties. Typically, I set the Account property to System.ServiceProcess.ServiceAccount.LocalSystem, so that it can be installed. This account probably won't have sufficient privileges to accomplish what my code is trying to do, so someone will need to open the Services Manager and change this to a valid account. I could hard-code the Name and Password of an account that I know has sufficient privileges, but this ties my application too tightly to a single domain or server or organization. I would rather keep it flexible enough that it can run anywhere. And besides, the account under which a service runs is really a deployment issue, so others should be making these decisions and they should be forced to think about this at deployment time.

Below is sample code for the installer class

[RunInstaller(true)]
public partial class Installer1 : Installer
{
    public Installer1()
    {
        InitializeComponent();
        ServiceInstaller si = new ServiceInstaller();
        ServiceProcessInstaller spi = new ServiceProcessInstaller();

        si.ServiceName = "DGWinSvc"; // this must match the ServiceName specified in Service1.
        si.DisplayName = "DGWinSvc"; // this will be displayed in the Services Manager.
        si.Description = "A test service that takes some action every 30 seconds";
        this.Installers.Add(si);

        spi.Account = System.ServiceProcess.ServiceAccount.LocalSystem; // run under the system account.
        spi.Password = null;
        spi.Username = null;
        this.Installers.Add(spi);
    }
}

After your code is tested and compiled, you can deploy it to a server. Copy to a location on the server the service EXE and any associated DLLs, Config files or other objects required for it to run. The server must have the .Net framework installed. If it has the framework, it should have a program called InstallUtil.exe. You can find this program in the Windows folder under Microsoft.NET\Framework in the subfolder corresponding to the .Net CLR version under which you compiled the service. On my server, I found InstallUtil.exe in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727. Open a command prompt, change to the location of InstallUtil.exe and run the following command
INSTALLUTIL <full path of Windows Service Executable>

You can later uninstall the service with the following command

INSTALLUTIL /u <full path of Windows Service Executable>

Now open the Services Manager applet (under Windows Administrative Tools) and refresh the list of services. You should see your service listed with the DisplayName you assigned in the Installer class. Right-click this service and select Properties to display the Service Properties dialog. Click the "Log On" tab, select "A particular user" and enter the name and password of the user under which this service should run. You may need to create this user. It should have permission to access all resources that the service needs to access. Click the OK button to save these changes and close the dialog.

Of course, you can also write a setup project to your solution if you want to automate the deployment process. This article does not cover that.

To start the service, right-click the service in the Services Manager and select Start.  You can use the same applet to stop the service. Right-click its name and select Stop. Alternatively, you can stop and start the service from the command line with the following commands

NET START <ServiceName>
NET STOP <ServiceName>

where <ServiceName> s the ServiceInstaller ServiceName property specified in our installer class. For our example, we would type. This is a useful if you want to script the starting and stopping of your service.

Windows Services are something that .Net got right very early and hasn't needed to change. Creating useful services is easy with the .Net framework.

You can download a simple Windows service at DGWinSvc.zip (28.05 KB).

 

Sunday, November 1, 2009 4:40:13 AM (GMT Standard Time, UTC+00:00)