Monday, January 13, 2014

How to build a solution using c# code in .NET 4.5 and retrieve the build result


Following is the code using which you can perform automated compilation of visual studio solutions through C#. First of all let’s retrieve the executing assembly path to write the output log of build activity performed using C#.
//retrieve assembly execution path
string assemblyExecutionPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string logFilePath = assemblyExecutionPath.Remove(assemblyExecutionPath.LastIndexOf("\\") + 1) + "build.log";
Let’s create a collection to hold the output –
OutputHeaderRow = new List<string>();
OutputItemRow = new List<string>();
Let’s say the path of the solution to build using C# code is present in following variable - string artifactPath = @"C:\Kunal_AppDev\New folder\Test Data Solution\ MySolution.sln"
Following is the remaining complete code –

try
{
                    // Instantiate a new FileLogger to generate build log
                    FileLogger logger = new FileLogger(); 

                    // Set the logfile parameter to indicate the log destination
                    logger.Parameters = @"logfile=" + logFilePath; 

                    ProjectCollection pc = new ProjectCollection(); 

                    Dictionary<string, string> GlobalProperty = new Dictionary<string, string>();
                    GlobalProperty.Add("Configuration", "Debug");
                    GlobalProperty.Add("Platform", "Any CPU"); 

                    BuildRequestData buildRequest = new BuildRequestData(artifactPath, GlobalProperty, null, new string[] { "Build" }, null); 

                    //register file logger using BuildParameters
                    BuildParameters bp = new BuildParameters(pc);
                    bp.Loggers = new List<Microsoft.Build.Framework.ILogger> { logger }.AsEnumerable();

                    //build solution
                    BuildResult buildResult = BuildManager.DefaultBuildManager.Build(bp, buildRequest); 

                    //Unregister all loggers to close the log file               
                    pc.UnregisterAllLoggers(); 

                    //read lines from log file having project build output details
                    string[] solutionBuildOutputs = File.ReadAllLines(logFilePath); 

                    //write the result of solution build to html report
                    OutputHeaderRow.Add("Artifact;Build Result"); 

                    //split the contents of logger file to retrieve project build details
                    string[] splitter = { "__________________________________________________" };
                    string loggerOutput = File.ReadAllText(logFilePath);
                    string[] projectResults = loggerOutput.Split(splitter, StringSplitOptions.None);
                    foreach (string projectBuildDetails in projectResults)
                    {
                        if (projectBuildDetails.Contains("(default targets):"))
                        {
                            if (projectBuildDetails.Contains("Done building project \""))
                            {
                                //write the result of failed projects build to html report
                                string[] lines = projectBuildDetails.Split("\n".ToCharArray());
                                string buildFailedProjectName = lines.Where(x => x.Contains("Done building project \"")).FirstOrDefault();
                                buildFailedProjectName = buildFailedProjectName.Replace("Done building project ", string.Empty).Trim();
                                buildFailedProjectName = buildFailedProjectName.Replace("\"", string.Empty);
                                buildFailedProjectName = buildFailedProjectName.Replace(" -- FAILED.", string.Empty);
                                OutputItemRow.Add(buildFailedProjectName + ";FAILED");
                            }
                            else
                            {
                                //write the result of successfully built projects to html report
                                string[] lines = projectBuildDetails.Split("\n".ToCharArray());
                                string buildSuccededProjectName = lines.Where(x => x.Contains(" (default targets):")).FirstOrDefault().Replace("\" (default targets):", "");
                                string finalProjectName = buildSuccededProjectName.Substring(buildSuccededProjectName.LastIndexOf("\\") + 1);
                                OutputItemRow.Add(finalProjectName + ";SUCCEEDED");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    //delete log file
                    File.Delete(logFilePath);
                }
Following screenshot shows the build result output in debug mode contained in string collection. This you can write to file or show in grid and anything as per your requirement –


 
Hope this helps.
Cheers…
Happy Building!!

2 comments:

  1. Really helpful. Thank you. As a feedback, I recommend that you explain your code a little more. Specially how to detect failed projects and successfully build projects.

    ReplyDelete
  2. Hi saeed, Thanks for the valuable feedback. I think I have already written the logic to detec failed and successful projects.OutputItemRow variable is aready showing this result as depicted in last screenshots. :)

    ReplyDelete