Monday, 17 December 2012

Diagnosing problems with Process Explorer


I recently upgraded an instance of Team Foundation Server 2010 to the 2012 version. The core upgrade process went very smoothly. The problem came with my customised build templates which used a custom activity written in C#. I was expecting one error, which I tried to fix before even attempting a build. This first error was that my custom activity was written against the TFS 2010 client assemblies:

Microsoft.TeamFoundation.Build.Client, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.TeamFoundation.Build.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.TeamFoundation.Client, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.TeamFoundation.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.TeamFoundation.WorkItemTracking.Client, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

These had to be changed to the TFS 2012 (Version 11.0.0.0) assemblies. So I upgraded and rebuilt the assembly holding my custom activity.

However, running a build after the upgrading my custom activity still gave me an error:

TF215097: An error occurred while initializing a build for build definition \[Team Project Name]\[My Build Name]: Cannot create unknown type '{clr-namespace:StealFocus.TfsExtensions.Workflow.Activities;assembly=StealFocus.TfsExtensions}UpdateBuildNumber'.

For some reason my "UpdateBuildNumber" class could not be created. That type could not even be found.

Time to poke around and see what is happening.

After checking some obvious things (were all dependencies available on the Build Agent, checking Fusion Log etc), I used Process Explorer (http://technet.microsoft.com/en-gb/sysinternals/bb896653.aspx) to look at the "TFSBuildServiceHost.exe" process and see if my assembly was even loading.

Starting up Process Explorer, I got a list of all processes on the local machine. I know I'm looking for "TFSBuildServiceHost.exe" as that is the executable for the Team Build service.


I can look at the detail of "TFSBuildServiceHost.exe", including all loaded .NET assemblies.


Looking down the list of loaded assemblies, my "StealFocus.TfsExtensions.dll" (which holds my custom activity) is not loaded at all, so it looks like there's quite a fundamental problem.

The thought occurred to me that I compiled my upgraded custom assembly against .NET 4.5, perhaps the TFS Build Agent is a .NET 4.0 application. This would mean the TFS Build Agent would be unable to load my assembly. As a rule of thumb, a .NET application cannot load assemblies from a later .NET Framework version. As an aside, the CLR version indicated as "v4.0.30319.17929" in the information above is misleading, the .NET Framework 4.5 still uses the CLR v4.0. The CLR saying "v4.0.30319.17929" did not mean it was a .NET 4.0 application.

So I rebuilt my upgraded assembly against .NET 4.0 and the build completed successfully. Looking into the detail with Process Explorer once more, I saw the following:


My assembly ("StealFocus.TfsExtensions.dll") had indeed loaded.

Problem solved.

So Process Explorer was a very useful tool to see what was happening under the hood. It showed me that my assembly was not loaded, which triggered my thought process about .NET Framework versions.

Monday, 10 December 2012

Cloud "Forecast"?


It's worth re-capping a couple of points from my previous post talking about operational cost reduction using Windows Azure. A key benefit of using the cloud is the ability to quickly and easily tear down environments, this includes test environments. If you are not using a test environment, then simply delete it and recreate it later when you need it. This can give you very large cost reductions.

With this in mind, I have created an application that will automatically tear down (or create) cloud resources on a schedule. The application can be run as a console or installed as a windows service.

At the moment you can:
  • Delete "Hosted Services" on a schedule.
  • Create "Hosted Services" on a schedule.
  • Delete Storage Tables on a schedule.
  • Delete Storage Blob Containers on a schedule.
Additional features will be added in time.

You can see the GitHub project here: https://github.com/StealFocus/Forecast

An example configuration is as follows:


  <stealFocusForecastConfiguration 
    xmlns="urn:StealFocus.Forecast.Configuration">
    <scheduleDefinitions>
      <scheduleDefinition name="MorningOutOfHours">
        <days>
          <day name="Monday" startTime="00:00:00" endTime="07:59:59" />
          <day name="Tuesday" startTime="00:00:00" endTime="07:59:59" />
          <day name="Wednesday" startTime="00:00:00" endTime="07:59:59" />
          <day name="Thursday" startTime="00:00:00" endTime="07:59:59" />
          <day name="Friday" startTime="00:00:00" endTime="07:59:59" />
        </days>
      </scheduleDefinition>
      <scheduleDefinition name="BusinessHours">
        <days>
          <day name="Monday" startTime="08:00:00" endTime="18:00:00" />
          <day name="Tuesday" startTime="08:00:00" endTime="18:00:00" />
          <day name="Wednesday" startTime="08:00:00" endTime="18:00:00" />
          <day name="Thursday" startTime="08:00:00" endTime="18:00:00" />
          <day name="Friday" startTime="08:00:00" endTime="18:00:00" />
        </days>
      </scheduleDefinition>
      <scheduleDefinition name="EveningOutOfHours">
        <days>
          <day name="Monday" startTime="18:00:01" endTime="23:59:59" />
          <day name="Tuesday" startTime="18:00:01" endTime="23:59:59" />
          <day name="Wednesday" startTime="18:00:01" endTime="23:59:59" />
          <day name="Thursday" startTime="18:00:01" endTime="23:59:59" />
          <day name="Friday" startTime="18:00:01" endTime="23:59:59" />
        </days>
      </scheduleDefinition>
      <scheduleDefinition name="Weekend">
        <days>
          <day name="Saturday" startTime="00:00:00" endTime="23:59:59" />
          <day name="Sunday" startTime="00:00:00" endTime="23:59:59" />
        </days>
      </scheduleDefinition>
    </scheduleDefinitions>
    <windowsAzure>
      <subscriptions>
        <subscription
          id="myArbitraryAzureSubscriptionName"
          subscriptionId="GUID"
          certificateThumbprint="0000000000000000000000000000000000000000" />
      </subscriptions>
      <hostedService>
        <packages>
          <package
            id="myArbitraryPackageName"
            storageAccountName="myAzureStorageAccountName"
            containerName="MyContainer"
            blobName="MyPackage.cspkg" />
        </packages>
        <deploymentDeletes>
          <deploymentDelete
            serviceName="myAzureServiceName"
            pollingIntervalInMinutes="10"
            subscriptionConfigurationId="myArbitraryAzureSubscriptionName">
            <deploymentSlots>
              <deploymentSlot name="Staging" />
              <deploymentSlot name="Production" />
            </deploymentSlots>
            <schedules>
              <schedule scheduleDefinitionName="MorningOutOfHours" />
              <schedule scheduleDefinitionName="EveningOutOfHours" />
              <schedule scheduleDefinitionName="Weekend" />
            </schedules>
          </deploymentDelete>
        </deploymentDeletes>
        <deploymentCreates>
          <deploymentCreate
            subscriptionConfigurationId="myArbitraryAzureSubscriptionName"
            windowsAzurePackageId="myArbitraryPackageName"
            serviceName="myAzureServiceName"
            deploymentName="MyName"
            deploymentLabel="MyLabel"
            deploymentSlot="Production"
            packageConfigurationFilePath="C:\PathTo\MyPackageConfiguration.cscfg"
            treatWarningsAsError="true"
            startDeployment="true"
            pollingIntervalInMinutes="10">
            <schedules>
              <schedule scheduleDefinitionName="BusinessHours" />
            </schedules>
          </deploymentCreate>
        </deploymentCreates>
      </hostedService>
      <storageService>
        <storageAccounts>
          <storageAccount
            storageAccountName="myStorageAccountName"
            storageAccountKey="myStorageAccountKey" />
        </storageAccounts>
        <tableDeletes>
          <tableDelete
            id="myArbitraryTableDeleteId"
            storageAccountName="myStorageAccountName"
            pollingIntervalInMinutes="60">
            <storageTables>
              <storageTable tableName="myAzureTableName1" />
              <storageTable tableName="myAzureTableName2" />
            </storageTables>
            <schedules>
              <schedule scheduleDefinitionName="MorningOutOfHours" />
              <schedule scheduleDefinitionName="EveningOutOfHours" />
              <schedule scheduleDefinitionName="Weekend" />
            </schedules>
          </tableDelete>
        </tableDeletes>
        <blobContainerDeletes>
          <blobContainerDelete
            id="myArbitraryBlobContainerDeleteId"
            storageAccountName="myStorageAccountName"
            pollingIntervalInMinutes="60">
            <blobContainers>
              <blobContainer blobContainerName="myAzureBlobContainerName1" />
              <blobContainer blobContainerName="myAzureBlobContainerName2" />
            </blobContainers>
            <schedules>
              <schedule scheduleDefinitionName="MorningOutOfHours" />
              <schedule scheduleDefinitionName="EveningOutOfHours" />
              <schedule scheduleDefinitionName="Weekend" />
            </schedules>
          </blobContainerDelete>
        </blobContainerDeletes>
      </storageService>
    </windowsAzure>
  </stealFocusForecastConfiguration>


Monday, 3 December 2012

Amazon Web Services


Every day this year, on average, AWS added the same server capacity to its public cloud as it took to run the Amazon.com retail business back in 2003, when it had $5.2bn in revenues. Amazon had "a whole lot of servers" back then in 2003…

This time last year, AWS execs were bragging that the public cloud, on average through 2011, was adding enough server capacity each day to run Amazon.com when it was a $2.76bn business in 2000.” - http://www.theregister.co.uk/2012/11/29/amazon_aws_update_jassy/

Wow.

About Me