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

发布于 2024-08-15 03:49:29 字数 178 浏览 6 评论 0 原文

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

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

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

I've checked out a branch of C# code from source control. It contains maybe 50 projects in various folders. There's no existing .sln file to be found.

I intended to create a blank solution to add existing solutions. The UI only lets me do this one project at a time.

Is there something I'm missing? I'd like to specify a list of *.csproj files and somehow come up with a .sln file that contains all the projects.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

我不吻晚风 2024-08-22 03:49:29

递归扫描脚本目录中的 .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()

A PowerShell implementation that recursively scans the script directory for .csproj files and adds them to a (generated) 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()
Saygoodbye 2024-08-22 03:49:29

生成可执行文件的 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);
    }
  }
}

A C# implementation that produces an executable, which creates a solution containing all unique *.csproj files from the directory and subdirectories it is executed in.

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);
    }
  }
}
花开雨落又逢春i 2024-08-22 03:49:29

这里已经有很多答案,但没有一个像这个 powershell oneliner 那样清晰

Get-ChildItem -Recurse -Include *.csproj | ForEach-Object { dotnet sln add $_ }

Plenty of answers here already, but none quite as clear as this powershell oneliner

Get-ChildItem -Recurse -Include *.csproj | ForEach-Object { dotnet sln add $_ }
○闲身 2024-08-22 03:49:29

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

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

There is extension for VS available, capable of adding all projects in selected directory (and more):

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

八巷 2024-08-22 03:49:29

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

在此处输入图像描述

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

Use Visual Studio Extension "Add Existing Projects". It works with Visual Studio 2012, 2013, 2015, 2017.

enter image description here

To use the extension, open the Tools menu and choose Add Projects.

恋竹姑娘 2024-08-22 03:49:29

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

You might be able to write a little PowerShell script or .NET app that parses all the projects' .csproj XML and extracts their details (ProjectGuid etc.) then adds them into the .sln file. It'd be quicker and less risky to add them all by hand, but an interesting challenge nonetheless.

野却迷人 2024-08-22 03:49:29

注意:这仅适用于 Visual Studio 2010

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

Note: This is only for Visual Studio 2010

Found here is a cool add in for Visual Studio 2010 that gives you a PowerShell console in VS to let you interact with the IDE. Among many other things you can do using the built in VS extensibility as mentioned by @Avram, it would be pretty easy to add files or projects to a solution.

日暮斜阳 2024-08-22 03:49:29

这是 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()

Here is a PowerShell version of Bertrand's script which assumes a Src and Test directory next to the solution file.

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()
失退 2024-08-22 03:49:29

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

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

if you open the sln file with notepad you can see the format of the file which is easy to understand but for more info take a look @ Hack the Project and Solution Files .understanding the structure of the solution files you can write an application which will open all project files and write the application name ,address and GUID to the sln file .

of course I think if it's just once you better do it manually

东京女 2024-08-22 03:49:29

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

查看该项目

GitHub

  SolutionGenerator.exe --folder C:\git\SomeSolutionRoot --output MySolutionFile.sln

Every answer seems to flatten the directory structure (all the projects are added to the solution root, without respecting the folder hierarchy). So, I coded my own console app that generates the solution and uses solution folders to group them.

Check out the project in GitHub

Usage

  SolutionGenerator.exe --folder C:\git\SomeSolutionRoot --output MySolutionFile.sln
甜`诱少女 2024-08-22 03:49:29

安装 dotnet core 后,您可以从 git bash 执行此操作:

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

生成的解决方案可与为旧 .NET Framework 创建的 csproj 配合使用

when you have dotnet core installed, you can execute this from git bash:

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

the generated solution works with csproj created for old .NET Framework.

秋风の叶未落 2024-08-22 03:49:29

这是 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");
            }
        }
    }
}

Here is Bertrand's solution updated for
Microsoft Visual Studio Solution File, Format Version 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(@
quot;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(@
quot;        {{{guid}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU");
                    writer.WriteLine(@
quot;        {{{guid}}}.Debug|Any CPU.Build.0 = Debug|Any CPU");
                }

                writer.WriteLine("  EndGlobalSection");
                writer.WriteLine("EndGlobal");
            }
        }
    }
}
甜宝宝 2024-08-22 03:49:29

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

Depends on visual studio version.
But the name of this process is "Automation and Extensibility for Visual Studio"
http://msdn.microsoft.com/en-us/library/t51cz75w.aspx

野侃 2024-08-22 03:49:29

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

这是一个针对 vs2010 的免费插件,可以做到这一点以及更多
如果项目属于 tfs

Check this out:
http://nprove.codeplex.com/

It is a free addin for vs2010 that does that and more
if the projects are under the tfs

谁与争疯 2024-08-22 03:49:29

以 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));
        }
    }
}

Building on Bertrand's answer at https://stackoverflow.com/a/16069782/492 - make a console app out of this and run it in the root folder where you want the VS 2015 Solution to appear. It works for C# & VB (hey! be nice).

It overwrites anything existing but you source control, right?

Check a recently used .SLN file to see what the first few writer.WriteLine() header lines should actually be by the time you read this.

Don't worry about the project type GUID Ptoject("0") - Visual Studio will work that out and write it in when you save the .sln file.

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));
        }
    }
}
嗳卜坏 2024-08-22 03:49:29

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

If you select 'Show all Files' in the Solution Explorer, you can than view all the files and folers and select them and right click to add them using 'Include in Project'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文