37

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

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

有什么我想念的吗?我想指定一个 *.csproj 文件列表,并以某种方式提出一个包含所有项目的 .sln 文件。

4

16 回答 16

22

递归扫描脚本目录中的 .csproj 文件并将它们添加到(生成的)All.sln 的 PowerShell 实现:

$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()
于 2010-05-17T13:00:06.073 回答
16

生成可执行文件的 AC# 实现,它创建一个解决方案,其中包含执行它的目录和子目录中的所有唯一 *.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);
    }
  }
}
于 2013-04-17T20:34:57.537 回答
9

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

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

于 2015-02-01T21:24:17.523 回答
5

使用 Visual Studio 扩展“添加现有项目”。它适用于 Visual Studio 2012、2013、2015、2017。

在此处输入图像描述

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

于 2018-09-24T21:27:44.627 回答
4

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

于 2009-12-11T21:54:36.587 回答
3

注意:这仅适用于 Visual Studio 2010

在这里可以找到一个很酷的 Visual Studio 2010 插件,它在 VS 中为您提供了一个 PowerShell 控制台,让您可以与 IDE 进行交互。您可以使用@Avram 提到的内置 VS 可扩展性来执行许多其他操作,将文件或项目添加到解决方案非常容易。

于 2010-04-24T17:10:42.427 回答
3

这是 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()
于 2015-10-07T02:05:41.557 回答
1

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

当然我认为如果只是一次你最好手动做

于 2009-12-11T22:16:57.340 回答
1

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

查看GitHub中的项目

用法

  SolutionGenerator.exe --folder C:\git\SomeSolutionRoot --output MySolutionFile.sln
于 2017-09-24T18:23:00.820 回答
1

安装 dotnet core 后,可以从 git bash 执行:

donet new sln; find . -name "*.csproj" -exec dotnet sln add {} \;

生成的解决方案适用于为旧 .NET Framework 创建的csproj 。

于 2021-04-23T17:08:08.877 回答
0

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

于 2009-12-11T22:06:46.457 回答
0

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

如果项目在 tfs 下,它是 vs2010 的免费插件

于 2012-12-12T07:57:00.413 回答
0

基于 Bertrand 在https://stackoverflow.com/a/16069782/492上的回答- 制作一个控制台应用程序并在您希望 VS 2015 解决方案出现的根文件夹中运行它。它适用于 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));
        }
    }
}
于 2016-10-10T01:10:06.297 回答
0

这是Bertrand为 Microsoft Visual Studio 解决方案文件更新 的解决方案,格式版本 12.00

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace AllSolutionGenerator
{
    internal static class Program
    {
        private static void Main()
        {
            var dir = new DirectoryInfo(Directory.GetCurrentDirectory());

            var projects = new Dictionary<string, string>();
            var guid1 = Guid.NewGuid().ToString().ToUpperInvariant();

            using (var writer = new StreamWriter("all.sln", false, Encoding.UTF8))
            {
                writer.WriteLine("Microsoft Visual Studio Solution File, Format Version 12.00");

                foreach (var file in dir.GetFiles("*.csproj", SearchOption.AllDirectories))
                {
                    var fileName = Path.GetFileNameWithoutExtension(file.Name);

                    if (!projects.ContainsKey(fileName))
                    {
                        var guid = Guid.NewGuid().ToString().ToUpperInvariant();

                        projects.Add(fileName, guid);

                        writer.WriteLine(@$"Project(""{{{guid1}}}"") = ""{fileName}"", ""{file.FullName}"",""{guid}""");
                        writer.WriteLine("EndProject");
                    }
                }

                writer.WriteLine("Global");
                writer.WriteLine("  GlobalSection(SolutionConfigurationPlatforms) = preSolution");
                writer.WriteLine("      Debug|Any CPU = Debug|Any CPU");
                writer.WriteLine("      Release|Any CPU = Release|Any CPU");
                writer.WriteLine("  EndGlobalSection");
                writer.WriteLine("  GlobalSection(ProjectConfigurationPlatforms) = postSolution");

                foreach (var (_, guid) in projects)
                {
                    writer.WriteLine(@$"        {{{guid}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU");
                    writer.WriteLine(@$"        {{{guid}}}.Debug|Any CPU.Build.0 = Debug|Any CPU");
                }

                writer.WriteLine("  EndGlobalSection");
                writer.WriteLine("EndGlobal");
            }
        }
    }
}
于 2021-12-07T11:50:14.797 回答
0

这里已经有很多答案了,但没有一个比这个 powershell oneliner 更清楚

Get-ChildItem -Recurse -Include *.csproj | ForEach-Object { dotnet sln add $_ }
于 2022-02-07T22:35:07.490 回答
-2

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

于 2011-07-29T14:15:54.947 回答