Created
September 7, 2015 21:55
-
-
Save 3F/b1f613511737121a4bd1 to your computer and use it in GitHub Desktop.
How to detect the first & last project of build-order in solution of Visual Studio. And how to use directly SBE-Scripts engine from C# Mode. / Example for vsSolutionBuildEvent users
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Text; | |
using System.Text.RegularExpressions; | |
using ICommand = net.r_eg.vsSBE.Actions.ICommand; | |
using ISolutionEvent = net.r_eg.vsSBE.Events.ISolutionEvent; | |
namespace vsSolutionBuildEvent | |
{ | |
public class CSharpMode | |
{ | |
/// <summary> | |
/// based on https://gist.github.com/3F/a77129e3978841241927 | |
/// </summary> | |
private class ProjectsMap | |
{ | |
protected List<string> order = new List<string>(); | |
protected Dictionary<string, Project> projects = new Dictionary<string, Project>(); | |
public Project getLast() | |
{ | |
if(order.Count < 1) { | |
return new Project() { name = "The Last project is Undefined", path = "?" }; | |
} | |
return projects[order[order.Count - 1]]; | |
} | |
public Project getFirst() | |
{ | |
if(order.Count < 1) { | |
return new Project() { name = "The First project is Undefined", path = "?" }; | |
} | |
return projects[order[0]]; | |
} | |
/// <param name="sln">Full path to solution</param> | |
public ProjectsMap(string sln) | |
{ | |
Regex rProject = new Regex("^Project\\(\"(?<TypeGuid>.*)\"\\)\\s*=\\s*\"(?<Name>.*)\"\\s*,\\s*\"(?<Path>.*)\"\\s*,\\s*\"(?<Guid>.*)\"$"); | |
Regex rProperty = new Regex("^(?<PName>[^=]*)\\s*=\\s*(?<PValue>[^=]*)$"); | |
Dictionary<string, List<string>> map = new Dictionary<string, List<string>>(); | |
using(StreamReader reader = new StreamReader(sln, Encoding.Default)) | |
{ | |
string line; | |
while((line = reader.ReadLine()) != null) | |
{ | |
line = line.Trim(); | |
if(!line.StartsWith("Project(", StringComparison.Ordinal)) { | |
continue; | |
} | |
Match m = rProject.Match(line); | |
if(!m.Success) { | |
throw new Exception("incorrect line"); | |
} | |
if(String.Equals("{2150E333-8FDC-42A3-9474-1A3956D46DE8}", m.Groups["TypeGuid"].Value.Trim(), StringComparison.OrdinalIgnoreCase)) { | |
continue; //SolutionFolder | |
} | |
string pGuid = m.Groups["Guid"].Value.Trim(); | |
projects[pGuid] = new Project() { name = m.Groups["Name"].Value, path = m.Groups["Path"].Value }; | |
map[pGuid] = new List<string>(); | |
while((line = reader.ReadLine()) != null && (line != "EndProject")) | |
{ | |
line = line.Trim(); | |
if(line.StartsWith("ProjectSection(ProjectDependencies)", StringComparison.Ordinal)) | |
{ | |
for(line = reader.ReadLine(); line != null; line = reader.ReadLine()) | |
{ | |
line = line.Trim(); | |
if(line.StartsWith("EndProjectSection", StringComparison.Ordinal)) { | |
break; | |
} | |
map[pGuid].Add(rProperty.Match(line).Groups["PName"].Value.Trim()); | |
} | |
} | |
} | |
} | |
} | |
// Build order | |
Func<string, bool> h = null; | |
h = delegate(string id) | |
{ | |
map[id].ForEach(dep => h(dep)); | |
if(!order.Contains(id)) { | |
order.Add(id); | |
} | |
return true; | |
}; | |
foreach(KeyValuePair<string, List<string>> project in map) | |
{ | |
h(project.Key); | |
if(!order.Contains(project.Key)) { | |
order.Add(project.Key); | |
} | |
} | |
} | |
} | |
private struct Project | |
{ | |
public string name; | |
public string path; | |
} | |
public static int Init(ICommand cmd, ISolutionEvent evt) | |
{ | |
ProjectsMap map = new ProjectsMap(@"$(SolutionPath)"); | |
// it should be in reverse order for 'Clean' type | |
string data = @" | |
#[( #[Build type] != Clean ) | |
{{ | |
#[var firstProject = {0}] #[var lastProject = {1}] | |
}} | |
else {{ | |
#[var firstProject = {1}] #[var lastProject = {0}] | |
}}] | |
"; | |
cmd.SBEScript.parse(String.Format(data, map.getFirst().name, map.getLast().name)); | |
return 0; | |
} | |
} | |
} |
Author
3F
commented
Sep 7, 2015
- Full example: https://github.com/3F/CI.MSBuild.Demo
- Link on page: http://vssbe.r-eg.net/doc/Examples/Demo/
v0.12.4+ is already contains similar logic in BuildComponent.
Now it should be easier, for example:
#[Build solution.path("app.sln").First.name]
#[Build solution.current.Last.path]
...
#[( #[Build solution.current.GuidList] ~= "{4262A1DC-768F-43CC-85F5-A4ED9CD034CC}" )
{
...
}]
...
etc.
Available a few variants for different modes.
http://vssbe.r-eg.net/doc/Scripts/SBE-Scripts/
http://vssbe.r-eg.net/doc/Modes/CSharp/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment