Welcome to MSDN Blogs Sign in | Join | Help

The following sample task illustrates how to add custom build step messages to the build process.

 

using System;

using Microsoft.Build.Framework;

using Microsoft.Build.Utilities;

using Microsoft.TeamFoundation.Client;

using Microsoft.TeamFoundation.Build.Proxy;

using System.Threading;

 

// This sample references Microsoft.Build.Framework.dll, Microsoft.Build.Utilities.dll,

// Microsoft.TeamFoundation.Build.Common.dll, Microsoft.TeamFoundation.Client.dll,

// System.dll, System.Web.Services.dll

 

namespace TeamBuildSampleTasks

{

    public class SampleTaskWithCustomBuildStep : Task

    {

        private string m_teamFoundationUrl;

        private string m_buildNumber;

        private string m_teamProject;

 

        [Required]

        public string TeamFoundationUrl

        {

            get { return m_teamFoundationUrl; }

            set { m_teamFoundationUrl = value; }

        }

 

        [Required]

        public string BuildNumber

        {

            get { return m_buildNumber; }

            set { m_buildNumber = value; }

        }

 

        [Required]

        public string TeamProject

        {

            get { return m_teamProject; }

            set { m_teamProject = value; }

        }

 

        public override bool Execute()

        {

            // Create TeamBuild BuildStore web service.

            TeamFoundationServer tfs = new TeamFoundationServer(m_teamFoundationUrl);

            BuildStore bs = (BuildStore)(tfs.GetService(typeof(BuildStore)));

           

            // buildUri is used later on to identify the build

            string buildUri = bs.GetBuildUri(m_teamProject, m_buildNumber);

 

            // This string is used internally in TeamBuild to identify the message.

            string buildStepName = "Sleep Messages";

            string buildStepMsg = "Build Step: Sleep and get random result";

 

            // Add the build step message to the build process and this will show up in the build report

            // now the status set to 'in progress'

            bs.AddBuildStep(buildUri, buildStepName, buildStepMsg);

 

            // Do task actions here. My sample does nothing but goes to a sound sleep and gets a random result :)

            Thread.Sleep(10000);

            bool result = GetRandomResult();

 

            //update the build step message with pass/fail information

            if(result)

                bs.UpdateBuildStep(buildUri, buildStepName, DateTime.Now, BuildStepStatus.Succeeded);

            else

                bs.UpdateBuildStep(buildUri, buildStepName, DateTime.Now, BuildStepStatus.Failed);

 

            // Log the result into build log file

            Log.LogMessage("SampleTaskWithCustomBuildStep completed, result: " + result);

 

            return true;

        }

 

        private bool GetRandomResult()

        {

            return ((1==new Random().Next() % 2) ? true : false);

        }

    }

}

 

There are several requests on how to publish test results to a TFS server without really creating a build. The build entry is a prerequisite for publishing test results, so you will need to create one and also create an associated project configuration against which the test results will be published. You can use TeamBuild web services to do this. Here is a sample:

 

The following sample creates a build named ‘SkeletonBuild001’ under TeamProject ‘MyTeamProject’ and Debug/X86 configuration which can be used to publish results against. Make sure that the drop location exists before publishing test results.

 

using Microsoft.TeamFoundation.Client;

using Microsoft.TeamFoundation.Build.Proxy;

using System;

 

// This sample references Microsoft.TeamFoundation.Build.Common.dll and Microsoft.TeamFoundation.Client.dll

namespace TeamBuildSamples

{

    class Program

    {

        static void Main(string[] args)

        {

            //Construct a buildstore object connecting to MyTFSServer

            BuildStore bStore = (BuildStore)(new TeamFoundationServer("http://MyTFSServer:8080").GetService(typeof(BuildStore)));

 

            //Create a build entry

           

            BuildData bd = new BuildData();

            //Fill in mandatory information for BuildData object

            bd.BuildNumber = "SkeletonBuild001";

            bd.BuildType = "DummyBuildType";

            bd.TeamProject = "MyTeamProject";

            // Make sure that this drop location exists, otherwise test publish will fail

            bd.DropLocation = @"\\vse1010\drops\SkeletonBuild001";

            bd.BuildMachine = "NoBuildMachine";

            bd.RequestedBy = Environment.UserName;

            bd.BuildStatus = "Successfully Completed";

            bd.BuildQuality = "Used for Publishing Test Results";

            // Add build entry to TeamBuild DB

            bStore.AddBuild("MyTeamProject", bd);

 

            string buildUri = bStore.GetBuildUri("MyTeamProject", "SkeletonBuild001");

 

            //Create platform/flavor information against which the test results will be published

 

            ProjectData pd = new ProjectData();

            //Fill in mandatory information for ProjectData object

            pd.FlavourName = "Debug";

            pd.PlatformName = "x86";

            pd.ProjectFile = "Dummy.sln";

            //Add project data entry for this build.

            bStore.AddProjectDetailsForBuild(buildUri, pd);

        }

    }

}

 

Namaste!

Yesterday, I was pleasantly surprised by my college mate, a good friend, Jothibasu contacting me. He was going through blogs on msdn and came across my blog J and contacted me. This brought back a lot of college day memories. I’m amazed, 10 years were passed by since we left the college, but the memories are still fresh. Thanks to the awesome power internet has in connecting people!

Oh, it is already 1½ months since I blogged. I feel time has been just flying, had a good time with kids during holidays. I wish you all a very happy and prosperous new year.

 

BTW, I’ve been reading a lot of blogs of late. One of my favorites is soma’s blog. I love his writings especially the ones where he talks about leadership and dream big.

Gijo, test lead for VSTF migration tools has started blogging. He has got plenty of first hand experience with these tools, so check out his blog regularly to learn tips and tricks about them!!

In a team environment, developers would need to use the same build configuration that is used to release the product builds and validate their implementation on their machines. TeamBuild offers this functionality through a feature called ‘Desktop Build’ – build on a developer box. Refer Uday’s blog to learn details on this subject.

 

Running ‘Desktop Build’ essentially means you run msbuild on TfsBuild.proj that belongs to a build type from a developer machine. The TeamBuild scripts including TfsBuild.proj are located at $/TeamProject/TeamBuildTypes/<BuildType>.

 

I’m listing some useful commands below:

 

msbuild TfsBuild.proj

Performs incremental build and runs tests

 

msbuild TfsBuild.proj /t:Clean

Performs clean only operation; It cleans common _binaries_ folder and all intermediate obj folders

 

msbuild TfsBuild.proj /t:Compile

Performs incremental compilation

 

msbuild TfsBuild.proj /t:Test

Runs tests only

 

msbuild TfsBuild.proj /t:DesktopRebuild

Performs clean à full compile à run tests. In Beta3 bits, tests are not included with ‘DesktopRebuild’. It is a bug, fixed in post B3 bits.

 

msbuild TfsBuild.proj /t:BinariesRoot=d:\foo /t:TestResultsRoot=d:\bar

We currently do not support overriding output directory. The workaround is to override ‘BinariesRoot’ where product binaries get copied and ‘TestResultsRoot’ where test results get uploaded.

 

msbuild TfsBuild.proj /p:RunCodeAnalysis=false

Disable code analysis in desktop build

 

msbuild TfsBuild.proj /t:RunTest=false

Do not run tests in desktop build

As you might already know, a managed component can be uniquely identified by assembly signing. Refer here to learn details on this subject. This can be executed in TeamBuild process as well.

 

Yesterday, I’ve answered a query on how to use password protected signing keys in TeamBuild. Thought it would be useful for all TeamBuild users, so here are the details:

 

Password protected signing keys may result in the following exception:

 

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets(1718,7): error MSB4018: The "ResolveKeySource" task failed unexpectedly.
System.InvalidOperationException: Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application.
   at Microsoft.Build.Shared.ExceptionHandling.RethrowUnlessFileIO(Exception e)
   at Microsoft.Build.Tasks.ResolveKeySource.ResolveAssemblyKey()
   at Microsoft.Build.Tasks.ResolveKeySource.Execute()
   at Microsoft.Build.BuildEngine.TaskEngine.ExecuteTask(ExecutionMode howToExecuteTask, Hashtable projectItemsAvailableToTask, BuildPropertyGroup projectPropertiesAvailableToTask, Boolean& taskClassWasFound)

 

It is because the build tries to open a dialog to accept password information and fails since TeamBuild process runs under a service where GUI cannot be invoked.

 

For this to work without prompting, the key needs to be exported into a key container crypto store on the build machine under the account that performs the build. Once exported, the build will not ask for a password anymore. The crypto store will do the signing and take care to keep private key safe.

 

One of the quicker ways to do this:

-          Logon to the build machine using the build service account

-          Run msbuild on any project that uses this signing key. It will prompt for the password and will export the key.

-          Now start the TeamBuild full build.

 

Namaste

The enterprise builds are huge and take a significant amount of build time. MSBuild offers an option to track the performance of each task and target executed in the build process which would be quite helpful for builders to identify the performance problems and improve the build time. I’m attempting to provide some details on how this can be plugged into TeamBuild.

 

MSBuild loggers have an option called PerformanceSummary to log this data. The user will need to add the following command line option to the msbuild process that runs on the build machine (refer here for more details on how to pass additional options to msbuild command line in TeamBuild):

 

/logger:FileLogger,Microsoft.Build.Engine;logfile=buildperf.log;encoding=Unicode;performancesummary

 

This creates the build log file that contains performance data buildperf.log at <builddir>\<teamproject>\<buildtype>\buildtype on the build machine. Currently, I could not find a way to upload this to drop location, because it needs to be uploaded after msbuild process exits and we currently don’t have a way to do this. BTW, this option is enabled in 'diagnostic' mode. So, user can pass '/v:diag' to msbuild command line and get this data in BuildLog.txt itself. It will have lots of other noise though.

 

Here is a snapshot of the performance data that msbuild process would log:

 

Project Performance Summary:

1302 ms  d:\builddir\TestProject\Take1\Sources\WindowsApplication1\WindowsApplication1\WindowsApplication1.csproj   1 calls

1593 ms  d:\builddir\TestProject\Take1\Sources\WindowsApplication2\WindowsApplication2.sln   1 calls

18549 ms  d:\builddir\TestProject\Take1\BuildType\TFSBuild.proj   1 calls

 

Target Performance Summary:

        * ms  Build                                      1 calls

        * ms  CoreCompile                                1 calls

        0 ms  Clean                                      1 calls

        0 ms  BeforeResGen                               1 calls

        0 ms  PostBuild                                  1 calls

        0 ms  BuildNumberOverrideTarget                  1 calls

        0 ms  BeforeClean                                1 calls

        0 ms  _CheckForInvalidConfigurationAndPlatform   1 calls

        0 ms  BeforeDropBuild                            1 calls

        0 ms  GetCopyToOutputDirectoryItems              1 calls

        0 ms  PackageBinaries                            1 calls

        0 ms  _CleanGetCurrentAndPriorFileWrites         1 calls

        0 ms  GetTargetPath                              1 calls

        0 ms  PreBuild                                   1 calls

        0 ms  _CopyFilesMarkedCopyLocal                  1 calls

        0 ms  _CheckForCompileOutputs                    1 calls

        0 ms  AssignTargetPaths                          1 calls

        0 ms  Compile                                    2 calls

        0 ms  BeforeBuild                                1 calls

        0 ms  _CopySourceItemsToOutputDirectory          1 calls

        0 ms  AfterBuild                                 1 calls

        0 ms  AfterResGen                                1 calls

        0 ms  AfterResolveReferences                     1 calls

        0 ms  Test                                       1 calls

        0 ms  AfterCompile                               2 calls

        0 ms  CoreBuild                                  1 calls

        0 ms  GetRedistLists                             1 calls

        0 ms  PrepareResources                           1 calls

        0 ms  AfterEndToEndIteration                     1 calls

        0 ms  AfterLabel                                 1 calls

        0 ms  ResolveReferences                          1 calls

        0 ms  BeforeEndToEndIteration                    1 calls

        0 ms  ValidateSolutionConfiguration              1 calls

        0 ms  BuildOnlySettings                          1 calls

        0 ms  DropBuild                                  1 calls

        0 ms  ResGen                                     1 calls

        0 ms  PrepareResourceNames                       1 calls

        0 ms  SplitResourcesByCulture                    1 calls

        0 ms  BeforeResolveReferences                    1 calls

        0 ms  AfterGet                                   1 calls

        0 ms  TeamBuild                                  1 calls

        0 ms  PrepareRdlFiles                            1 calls

        0 ms  CompileRdlFiles                            1 calls

        0 ms  AfterTest                                  1 calls

        0 ms  BeforeGet                                  1 calls

        0 ms  AfterDropBuild                             1 calls

        0 ms  BeforeLabel                                1 calls

        0 ms  EndToEndIteration                          1 calls

        0 ms  PrepareForRun                              1 calls

        0 ms  AfterClean                                 1 calls

        0 ms  GetFrameworkPaths                          1 calls

       10 ms  CopyFilesToOutputDirectory                 1 calls

       10 ms  PrepareForBuild                            1 calls

       10 ms  CopyLogFiles                               1 calls

       10 ms  CreateManifestResourceNames                1 calls

       10 ms  IncrementalClean                           1 calls

       20 ms  InitializeBuild                            1 calls

       40 ms  CoreClean                                  1 calls

       50 ms  CoreResGen                                 1 calls

       50 ms  CoreDropBuild                              1 calls

      150 ms  ResolveAssemblyReferences                  1 calls

      150 ms  BeforeTest                                 1 calls

      170 ms  InitializeEndToEndIteration                1 calls

      180 ms  BeforeCompile                              2 calls

      220 ms  CheckSettingsForEndToEndIteration          1 calls

     1332 ms  WindowsApplication2                        1 calls

     1462 ms  CoreLabel                                  1 calls

     2354 ms  InitializeWorkspace                        1 calls

     3976 ms  CoreGet                                    1 calls

     5318 ms  GetChangeSetsAndUpdateWorkItems            1 calls

        (* = timing was not recorded because of reentrancy)

 

Task Performance Summary:

        * ms  MSBuild                                    1 calls

        0 ms  RemoveDuplicates                           2 calls

        0 ms  CreateCSharpManifestResourceName           1 calls

        0 ms  GetFrameworkSDKPath                        1 calls

        0 ms  FindUnderPath                              5 calls

        0 ms  ReadLinesFromFile                          1 calls

        0 ms  AssignTargetPath                           5 calls

        0 ms  AssignCulture                              1 calls

        0 ms  CreateProperty                            12 calls

        0 ms  GetFrameworkPath                           1 calls

       10 ms  MakeDir                                    5 calls

       10 ms  Delete                                     1 calls

       10 ms  TeamBuildMessage                           3 calls

       10 ms  CreateItem                                17 calls

       20 ms  RemoveDir                                  1 calls