代码之家  ›  专栏  ›  技术社区  ›  Michael J Swart

将多个现有.csproj添加到Visual Studio解决方案的简单方法?

  •  32
  • Michael J Swart  · 技术社区  · 15 年前

    我已经从源代码管理中签出了C代码的一个分支。它在不同的文件夹中包含大约50个项目。找不到现有的.sln文件。

    我打算创建一个空白解决方案来添加现有的解决方案。用户界面一次只允许我做一个项目。

    我有什么东西不见了吗?我想指定一个*.csproj文件的列表,并以某种方式找到一个包含所有项目的.sln文件。

    13 回复  |  直到 6 年前
        1
  •  3
  •   Michael Baker    9 年前

    下面是Bertrand脚本的PowerShell版本,它假定解决方案文件旁边有一个SRC和TEST目录。

    function GetGuidFromProject([string]$fileName) {
        $content = Get-Content $fileName
    
        $xml = [xml]$content
        $obj = $xml.Project.PropertyGroup.ProjectGuid
    
        return [Guid]$obj[0]
    }
    
    $slnPath = "C:\Project\Foo.sln"
    
    $solutionDirectory = [System.IO.Path]::GetDirectoryName($slnPath)
    
    $srcPath = [System.IO.Path]::GetDirectoryName($slnPath)
    $writer = new-object System.IO.StreamWriter ($slnPath, $false, [System.Text.Encoding]::UTF8)
    
    $writer.WriteLine("Microsoft Visual Studio Solution File, Format Version 12.00")
    $writer.WriteLine("# Visual Studio 2013")
    
    $projects = gci $srcPath -Filter *.csproj -Recurse
    
    foreach ($project in $projects) {
       $fileName = [System.IO.Path]::GetFileNameWithoutExtension($project)
    
       $guid = GetGuidFromProject $project.FullName
    
       $slnRelativePath = $project.FullName.Replace($solutionDirectory, "").TrimStart("\")
    
       # Assume the project is a C# project {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
       $writer.WriteLine("Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""$fileName"", ""$slnRelativePath"",""{$($guid.ToString().ToUpper())}""")
       $writer.WriteLine("EndProject")
    }
    
    $writer.Flush()
    $writer.Close()
    $writer.Dispose()
    
        2
  •  21
  •   Alex Peck    9 年前

    一种PowerShell实现,递归扫描脚本目录中的.csproj文件并将其添加到(生成的)all.sln中:

    $scriptDirectory = (Get-Item $MyInvocation.MyCommand.Path).Directory.FullName
    $dteObj = [System.Activator]::CreateInstance([System.Type]::GetTypeFromProgId("VisualStudio.DTE.12.0"))
    
    $slnDir = ".\"
    $slnName = "All"
    
    $dteObj.Solution.Create($scriptDirectory, $slnName)
    (ls . -Recurse *.csproj) | % { $dteObj.Solution.AddFromFile($_.FullName, $false) }
    
    $dteObj.Solution.SaveAs( (Join-Path $scriptDirectory 'All.sln') ) 
    
    $dteObj.Quit()
    
        3
  •  15
  •   Bertrand    12 年前

    一种产生可执行文件的C实现,它创建一个解决方案,该解决方案包含执行该可执行文件所在目录及其子目录中所有唯一的*.csproj文件。

    class Program
    {
      static void Main(string[] args)
      {
        using (var writer = new StreamWriter("All.sln", false, Encoding.UTF8))
        {
          writer.WriteLine("Microsoft Visual Studio Solution File, Format Version 11.00");
          writer.WriteLine("# Visual Studio 2010");
    
          var seenElements = new HashSet<string>();
          foreach (var file in (new DirectoryInfo(System.IO.Directory.GetCurrentDirectory())).GetFiles("*.csproj", SearchOption.AllDirectories))
          {
            string fileName = Path.GetFileNameWithoutExtension(file.Name);
    
            if (seenElements.Add(fileName))
            {
              var guid = ReadGuid(file.FullName);
              writer.WriteLine(string.Format(@"Project(""0"") = ""{0}"", ""{1}"",""{2}""", fileName, file.FullName, guid));
              writer.WriteLine("EndProject");
            }
          }
        }
      }
    
      static Guid ReadGuid(string fileName)
      {
        using (var file = File.OpenRead(fileName))
        {
          var elements = XElement.Load(XmlReader.Create(file));
          return Guid.Parse(elements.Descendants().First(element => element.Name.LocalName == "ProjectGuid").Value);
        }
      }
    }
    
        4
  •  8
  •   kwesolowski    10 年前

    有可用的vs扩展,可以添加选定目录中的所有项目(及更多):

    http://www.cyotek.com/blog/visual-studio-extension-for-adding-multiple-projects-to-a-solution

        5
  •  4
  •   Chris Fulstow    15 年前

    您可能可以编写一个PowerShell脚本或.NET应用程序来解析所有项目的.csproj xml并提取它们的详细信息(projectguid等),然后将它们添加到.sln文件中。手工添加它们的速度更快,风险更小,但这仍然是一个有趣的挑战。

        6
  •  3
  •   smaclell    15 年前

    注: 这只适用于Visual Studio 2010

    发现 here 是一个很酷的Visual Studio 2010外接程序,它在VS中为您提供了一个PowerShell控制台,使您可以与IDE进行交互。使用@avram所提到的内置vs扩展性,您可以做许多其他事情,其中一件事就是向解决方案中添加文件或项目非常容易。

        7
  •  1
  •   Asha    15 年前

    如果您用记事本打开SLN文件,您可以看到文件的格式,这很容易理解,但要了解更多信息,请查看@ Hack the Project and Solution Files .了解解决方案文件的结构,您可以编写一个应用程序,该应用程序将打开所有项目文件,并将应用程序名称、地址和guid写入SLN文件。

    当然,如果只是一次,你最好手动操作

        8
  •  1
  •   Gerardo Grignoli    7 年前

    每个答案似乎都会使目录结构变平(所有项目都会添加到解决方案根目录中,而不考虑文件夹层次结构)。因此,我编写了自己的控制台应用程序,生成解决方案并使用解决方案文件夹对它们进行分组。

    签出项目 GitHub

    用法

      SolutionGenerator.exe --folder C:\git\SomeSolutionRoot --output MySolutionFile.sln
    
        9
  •  0
  •   Avram    15 年前

    取决于Visual Studio版本。
    但是这个过程的名字是“Visual Studio的自动化和可扩展性”
    http://msdn.microsoft.com/en-us/library/t51cz75w.aspx

        10
  •  0
  •   Jose Luis    12 年前

    看看这个: http://nprove.codeplex.com/

    它是VS2010的一个免费的加载项,可以实现这些功能。 如果项目在TFS下

        11
  •  0
  •   Community CDub    8 年前

    基于伯特兰的回答 https://stackoverflow.com/a/16069782/492 -从中创建一个控制台应用程序,并将其运行在您希望VS2015解决方案出现的根文件夹中。它适用于C&vb(嘿!好一点。

    它会覆盖除源代码管理之外的任何现有内容,对吗?

    检查最近使用过的.sln文件,查看前几个文件 writer.WriteLine() 标题行实际上应该在您阅读本文时出现。

    不要担心项目类型guid Ptoject("0") -Visual Studio将解决这个问题,并在保存.sln文件时将其写入。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace AddAllProjectsToNewSolution
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("starting");
                using (var writer = new StreamWriter("AllProjects.sln", false, Encoding.UTF8))
                {
                    writer.WriteLine("Microsoft Visual Studio Solution File, Format Version 14.00");
                    writer.WriteLine("# Visual Studio 14");
                    writer.WriteLine("VisualStudioVersion = 14.0.25420.1");
                    var seenElements = new HashSet<string>();
    
                    foreach (var file in (new DirectoryInfo(Directory.GetCurrentDirectory())).GetFiles("*.*proj", SearchOption.AllDirectories))
                    {
                        string extension = file.Extension;
                        if (extension != ".csproj" && extension != ".vbproj")
                        {
                            Console.WriteLine($"ignored {file.Name}");
                            continue;
                        }
    
                        Console.WriteLine($"adding {file.Name}");
    
                        string fileName = Path.GetFileNameWithoutExtension(file.Name);
    
                        if (seenElements.Add(fileName))
                        {
                            var guid = ReadGuid(file.FullName);
                            writer.WriteLine($"Project(\"0\") = \"{fileName}\", \"{GetRelativePath(file.FullName)} \", \"{{{guid}}}\"" );
                            writer.WriteLine("EndProject");
                        }
    
                    } 
                }
                 Console.WriteLine("Created AllProjects.sln. Any key to close");
                 Console.ReadLine();
            }
    
            static Guid ReadGuid(string fileName)
            {
                using (var file = File.OpenRead(fileName))
                {
                    var elements = XElement.Load(XmlReader.Create(file));
                    return Guid.Parse(elements.Descendants().First(element => element.Name.LocalName == "ProjectGuid").Value);
                }
            }
            // https://stackoverflow.com/a/703292/492
            static string GetRelativePath(string filespec, string folder = null)
            {
                if (folder == null)
                    folder = Environment.CurrentDirectory;
    
                Uri pathUri = new Uri(filespec);
                // Folders must end in a slash
                if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))
                    folder += Path.DirectorySeparatorChar;
    
                Uri folderUri = new Uri(folder);
                return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace('/', Path.DirectorySeparatorChar));
            }
        }
    }
    
        12
  •  0
  •   Marco Thomazini    6 年前

    使用Visual Studio扩展” Add Existing Projects “。它与Visual Studio 2012、2013、2015、2017配合使用。

    enter image description here

    要使用扩展名,请打开 工具 菜单选择 添加项目 .

        13
  •  -2
  •   Gabriël    13 年前

    如果在解决方案资源管理器中选择“显示所有文件”,则可以查看所有文件和后续文件并选择它们,然后右键单击以使用“包含在项目中”添加它们。