From 751ee0bdc69ef8ab46ab2f94bb5ba6c72b3a1707 Mon Sep 17 00:00:00 2001 From: ggrignoli Date: Sun, 24 Sep 2017 15:01:12 -0300 Subject: [PATCH] Changed to CommandLineParser. Added help & README.md. --- README.md | 25 +++++++++++++++++ Sources/Program.cs | 45 +++++++++++------------------- Sources/Properties/AssemblyInfo.cs | 3 +- Sources/SolutionGenerator.cs | 39 +++++++++++++++----------- Sources/SolutionGenerator.csproj | 4 +-- Sources/packages.config | 2 +- 6 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7335d5b --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Create a Visual Studio Solution from Existing Projects + +This console application traverse a folder tree finding every existing Visual Studio Project and adding them to a new solution. It creates 'solution folders' so the projects are grouped in the same hierarchy as in the file system. + +Usage: +``` + -f, --folder Required. Folder to traverse and where the solution will be + generated. + + -o, --output (Default: AllProjects.sln) FileName of the solution to + create. + + -e, --exclude (Default: .git,bin,obj,packages,node_modules) Comma + separated list of folders to exclude. + + -v, --verbose Verbose +``` + +Example: +``` + SolutionGenerator.exe --folder C:\git\SomeSolutionRoot --output MySolutionFile.sln +``` + +## Supported Project Types: +Right now it only supports *.csproj file types. It can be extended to other project types by correctly handling the each Project Type GUIDs. \ No newline at end of file diff --git a/Sources/Program.cs b/Sources/Program.cs index 9abb234..331ce2a 100644 --- a/Sources/Program.cs +++ b/Sources/Program.cs @@ -1,45 +1,32 @@ -using Fclp; +using CommandLine; using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; + +[assembly: CommandLine.AssemblyUsageAttribute("Finds all Visual Studio projects in a folder tree and adds them to a new solution file.")] namespace SolutionGenerator { - public class Arguments + public class Options { + [Option('f', "folder", HelpText = "Folder to traverse and where the solution will be generated.", Required = true)] public string Folder { get; set; } + [Option('o', "output", HelpText = "FileName of the solution to create.", DefaultValue = "AllProjects.sln")] public string SolutionFileName { get; set; } + [Option('e', "exclude", HelpText = "Comma separated list of folders to exclude.", DefaultValue = ".git,bin,obj,packages,node_modules")] + public string ExcludedFolders { get; set; } + [Option('v', "verbose", HelpText = "Verbose")] + public bool Verbose { get; set; } + } class Program { static void Main(string[] args) { - var parser = new FluentCommandLineParser(); - - parser.Setup(a => a.Folder) - .As('f', "folder") - .SetDefault(Directory.GetCurrentDirectory()); - - parser.Setup(a => a.SolutionFileName) - .As('d', "dest") - .Required(); - - var result = parser.Parse(args); - - if (result.HasErrors) - { - Console.WriteLine( result.ErrorText); - Console.Read(); - return; - } - - parser.Object.Folder = Path.GetFullPath(parser.Object.Folder); - - new SolutionGenerator(parser.Object).Render(); + var options = new Options(); + var isValid = Parser.Default.ParseArgumentsStrict(args, options); + if (isValid) + new SolutionGenerator(options).Render(); } + } } diff --git a/Sources/Properties/AssemblyInfo.cs b/Sources/Properties/AssemblyInfo.cs index 44f336a..11488e6 100644 --- a/Sources/Properties/AssemblyInfo.cs +++ b/Sources/Properties/AssemblyInfo.cs @@ -10,10 +10,9 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SolutionGenerator")] -[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyCopyright("Copyright 2017 - Gerardo Grignoli")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. diff --git a/Sources/SolutionGenerator.cs b/Sources/SolutionGenerator.cs index 4bb53ef..8fcfe9c 100644 --- a/Sources/SolutionGenerator.cs +++ b/Sources/SolutionGenerator.cs @@ -20,8 +20,7 @@ class FolderContent class SolutionGenerator { string Template = -@" -Microsoft Visual Studio Solution File, Format Version 12.00 +@"Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 @@ -31,23 +30,23 @@ class SolutionGenerator HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution -{1} - EndGlobalSection +{1} EndGlobalSection EndGlobal "; - private readonly Arguments _args; + private readonly Options _args; private HashSet _excludedFolders; - public SolutionGenerator(Arguments args) + public SolutionGenerator(Options args) { _args = args; - _excludedFolders = new HashSet(".git,bin,obj,packages,node_modules".Split(',')); + _excludedFolders = new HashSet(_args.ExcludedFolders.Split(',')); } public void Render() { var content = GetContent(_args.Folder); + content.FolderId = string.Empty; // Root folder is a special case StringBuilder projectSection = new StringBuilder(); StringBuilder folderSection = new StringBuilder(); @@ -58,6 +57,9 @@ public void Render() Path.Combine(_args.Folder, _args.SolutionFileName), string.Format(Template, projectSection.ToString(), folderSection.ToString()) ); + + Console.WriteLine("Done."); + } private void WriteContent(FolderContent content, StringBuilder projectSection, StringBuilder folderSection) @@ -67,7 +69,10 @@ private void WriteContent(FolderContent content, StringBuilder projectSection, S projectSection.AppendLine($"Project(\"{{2150E333-8FDC-42A3-9474-1A3956D46DE8}}\") = \"{ Path.GetFileName(dir.Path) }\", \"{ Path.GetFileName(dir.Path) }\", \"{{{dir.FolderId}}}\""); projectSection.AppendLine("EndProject"); - folderSection.AppendLine($" {{{dir.FolderId}}} = {{{content.FolderId}}}"); + if (!string.IsNullOrEmpty(content.FolderId)) + { + folderSection.AppendLine($" {{{dir.FolderId}}} = {{{content.FolderId}}}"); + } WriteContent(dir, projectSection, folderSection); } @@ -78,7 +83,8 @@ private void WriteContent(FolderContent content, StringBuilder projectSection, S projectSection.AppendLine($"Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{ Path.GetFileNameWithoutExtension(project) }\", \"{ MakeRelative(project) }\", \"{{{projectId}}}\""); projectSection.AppendLine("EndProject"); - folderSection.AppendLine($" {{{projectId}}} = {{{content.FolderId}}}"); + if (!string.IsNullOrEmpty(content.FolderId)) + folderSection.AppendLine($" {{{projectId}}} = {{{content.FolderId}}}"); } } @@ -89,7 +95,8 @@ private string MakeRelative(string path) FolderContent GetContent(string folder) { - Console.WriteLine(folder); + if(_args.Verbose) + Console.WriteLine(folder); var content = new FolderContent(); content.Path = folder; try @@ -102,15 +109,14 @@ FolderContent GetContent(string folder) var subContent = GetContent(subFolder); if (subContent.IsEmpty()) continue; - else if (subContent.SubDirectories.Count() == 0 && subContent.Projects.Count()==1) - content.Projects.AddRange(subContent.Projects); -// else if (subContent.Projects.Count == 1 && Path.GetFileNameWithoutExtension(subContent.Projects[0]) == folderName && subContent.SubDirectories.Count == 0) -// content.Projects.Add(subContent.Projects[0]); + else if (subContent.SubDirectories.Count() == 0 && subContent.Projects.Count()==1) + content.Projects.AddRange(subContent.Projects); // Flatten folders with only one project. else content.SubDirectories.Add(subContent); } } - catch (PathTooLongException) { } + catch (PathTooLongException) + { Console.Error.WriteLine($"PathTooLongException: {folder}"); } try { @@ -119,7 +125,8 @@ FolderContent GetContent(string folder) content.Projects.Add(subProj); } } - catch (PathTooLongException) { } + catch (PathTooLongException) + { Console.Error.WriteLine($"PathTooLongException: {folder}"); } return content; } } diff --git a/Sources/SolutionGenerator.csproj b/Sources/SolutionGenerator.csproj index d4afd02..f2183b9 100644 --- a/Sources/SolutionGenerator.csproj +++ b/Sources/SolutionGenerator.csproj @@ -33,8 +33,8 @@ 4 - - packages\FluentCommandLineParser.1.4.3\lib\net35\FluentCommandLineParser.dll + + packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll True diff --git a/Sources/packages.config b/Sources/packages.config index 0a540c7..d5fbc2e 100644 --- a/Sources/packages.config +++ b/Sources/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file