DotNetCurry Logo

Use InvokeProcess Activity in Visual Studio 2013 and Team Foundation Server 2013 to add Build Summary Information

Posted by: Gouri Sohoni , on 9/4/2014, in Category Visual Studio, VSTS & TFS
Views: 14535
Abstract: Call metrics utility through Custom (xaml and code) Activity and use InvokeProcess Activity in VS 2013 and TFS 2013 to add build summary information about the activity invoked.

In one of my previous articles I had explained how to use InvokeProcess activity in TFS. In this article, I will also explain how to add a build summary information about the activity invoked. The invoked activity in this case is to call Code Metrics utility after the build binaries are created. Based on the summary information, we can find out what is the maintainability index of the current assembly.

Code Metrics is an in-built utility in Visual Studio which provides information whether the code is maintainable or not. It is based on the algorithm developed by Carnegie Mellon University. This was later adapted and added by Microsoft in Visual Studio 2008 onwards. It is based on 4 categories - 

- Class Coupling (number of dependencies on other class)

- Depth of Inheritance (number of classes in the chain of inheritance)

- Cyclomatic Complexity (based on decision paths) and

- Lines of Code (number of executable lines) which results in Maintainability Index. This index is between 0 to 100, 0 to 9 is low, 10 to 19 is moderate and 20 to 100 is high. Based on this we can decide is our code is maintainable or not. It can be applied to code from Visual Studio as follows


In order to use Metrcrics.exe utility as InvokeProcess, download the power tool here. Once it is downloaded and installed, it is available in  “system drive\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\FxCop”

We will create an activity library in which we will add custom xaml activity as well as custom code activity. In xaml custom activity we will use InvokeProcess which in turn will call Code Metrics utility on the binaries created. We will send the results stored in xml file to code activity. In custom code activity, we will process the xml file and create a summary of the result. We will show the summary in build report by using WriteCustomSummaryInformation activity. We will have to provide path to the custom assemblies for the Build Controller. It is a better practice to create a common folder for all custom assemblies. We need to include .dll as a part of the project before check-in, so as to make the dll available in Source Control.

Let us walkthrough some steps for the same.

1. Create an empty solution and add ConsoleApplication to the solution

2. Provide some code so that the Metrics utility can be executed on this code

3. Add Activity Library

4. Start the wizard for New Build Definition from Build Explorer. From the Process tab click on Show Details for the process template.

5. Download default process template in the same folder as custom activity

6. Add this as an existing item to custom activity and change the Build Action to Content

7. Select the default xaml activity. In order to add new items to the Toolbox, choose Microsoft.TeamFoundation.Build.WorkFlow.dll from <drive name>\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\PrivateAssemblies

8. Set references to System.Drawing, PresentationFramework, Presentation.Core, WindowsBase, System.Activities.Presentation (in case you forget these references it will be pointed out one by one at the time of compiling)

9. Create a variable with name dropLocation with scope as sequence

10. Drag and drop sequence activity to Activity.xaml

11. Add GetEnvironmentVariable to sequence and enter following details


The Name will fetch the environmental variable for drop location and send it to the already created variable dropLocation with the help of Result.

12. Drag and drop InvokeProcess “Drop Loc” and provide following configurations.


13. You can also pass the folder path of the Metrics.exe to invokeProcess so as to have more flexibility. Results.xml file will be automatically created in the drop location which will create report of Code Metrics utility. The utility takes first option of /f: followed by the assembly to be executed the utility against. The second option /o: is followed by the results file name.

The arguments are passed by providing space in between them.

14. Drag and drop build message and warning as required in InvokeProcess and provide the values

The overall process looks as below


15. Build the solution. Include dll for activity library in the project and check-in.

16. Complete Build Definition creation and provide the path for the template as the newly added process workflow.

17. Create a folder CustomAssembly under root in Source control

18. Create a branch for the dll into the CustomAsembly folder


19. Check-in the branch

20. Select Manage Build Controller from Build Explorer – Action and provide the path for the custom assemblies


21. Save the build definition and trigger

22. The results file will be created in the drop folder

23. Add a code activity which will interpret xml file and add the data to Build Summary. Drag and drop CodeActivity below InvokeProcess

24. Create a variable for the sequence scope which will form the bridge between the workflow and code written.

The code looks as follow:

public sealed class CodeActivity1 : CodeActivity<string>
    // Define an activity input argument of type string
    public InArgument<string> TextdropLoc { get; set; }
    public OutArgument<string> TextMessage { get; set; }
    // If your activity returns a value, derive from CodeActivity<TResult>
    // and return the value from the Execute method.
    protected override string Execute(CodeActivityContext context)
        // Obtain the runtime value of the Text input argument
        string text = context.GetValue(this.TextdropLoc);
        //check the results.xml 
        XmlDocument doc = new XmlDocument();
        doc.Load(text + @"c:\results.xml");
        string msg = "MaintainabilityIndex Index \\n";
        XmlNodeList list=doc.DocumentElement.SelectNodes("//Metric[@Name='MaintainabilityIndex']");
        for (int i = 0; i < list.Count - 1; i++)
            string a = doc.DocumentElement.SelectNodes("//Metric[@Name='MaintainabilityIndex']")[i].ParentNode.ParentNode.Name;
            if (a == "Module")
                a = "Assembly:";
            else if (a == "Type")
                a = "Class:";
            else if (a == "Member")
                a = "Method:";
            string b = doc.DocumentElement.SelectNodes("//Metric[@Name='MaintainabilityIndex']")[i].ParentNode.ParentNode.Attributes["Name"].Value;
            string c = doc.DocumentElement.SelectNodes("//Metric[@Name='MaintainabilityIndex']")[0].Attributes["Value"].Value;
            msg+=a + " " + b + " " + c + "\\n";
        context.SetValue<string>(TextMessage, msg);
        context.SetValue(Result, msg);
        return msg;

26. Drag and drop WriteCustomSummaryInformation activity below CodeActivity and configure as shown here:


27. The overall xaml activity now looks as follows


28. Now trigger the build after check-in-in the dll and merging with the folder for custom assemblies. The summary looks as shown here:


And that’s how you add a build summary information about the activity invoked.

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on Google+
Further Reading - Articles You May Like!
Gouri Sohoni is a Trainer and Consultant for over two decades. She specializes in Visual Studio - Application Lifecycle Management (ALM) and Team Foundation Server (TFS). She is a Microsoft MVP in VS ALM, MCSD (VS ALM) and has conducted several corporate trainings and consulting assignments. She has also created various products that extend the capability of Team Foundation Server.

Page copy protected against web site content infringement 	by Copyscape

Feedback - Leave us some adulation, criticism and everything in between!