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:
[BuildActivity(HostEnvironmentOption.All]
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.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Gouri is a Trainer and Consultant on Azure DevOps and Azure Development. She has an experience of three decades in software training and consulting. She is a graduate from Pune University and PGDCA from Pune University. Gouri is a Microsoft Most Valuable Professional (MVP) - Developer Technologies (Azure DevOps), Microsoft Certified Trainer (MCT) and a Microsoft Certified Azure DevOps Engineer Expert. She has conducted over 150 corporate trainings on various Microsoft technologies. She is a speaker with Pune User Group and has conducted sessions on Azure DevOps, SQL Server Business Intelligence and Mobile Application Development. Gouri has written more than 75 articles on Azure DevOps, TFS, SQL Server Business Intelligence and SQL Azure which are published on
www.sqlservercurry.com and
www.dotnetcurry.com. You can connect with her on
LinkedIn.