Версия .NET 4.0 сборки Microsoft.Build содержит класс SolutionParser в пространстве имен Microsoft.Build.Construction, который анализирует файлы решений Visual Studio.
К сожалению, этот класс является внутренним, но я заключил некоторые из этих функций в класс, который использует отражение, чтобы получить некоторые общие свойства, которые могут оказаться полезными.
public class Solution
{
//internal class SolutionParser
//Name: Microsoft.Build.Construction.SolutionParser
//Assembly: Microsoft.Build, Version=4.0.0.0
static readonly Type s_SolutionParser;
static readonly PropertyInfo s_SolutionParser_solutionReader;
static readonly MethodInfo s_SolutionParser_parseSolution;
static readonly PropertyInfo s_SolutionParser_projects;
static Solution()
{
s_SolutionParser = Type.GetType("Microsoft.Build.Construction.SolutionParser, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false, false);
if (s_SolutionParser != null)
{
s_SolutionParser_solutionReader = s_SolutionParser.GetProperty("SolutionReader", BindingFlags.NonPublic | BindingFlags.Instance);
s_SolutionParser_projects = s_SolutionParser.GetProperty("Projects", BindingFlags.NonPublic | BindingFlags.Instance);
s_SolutionParser_parseSolution = s_SolutionParser.GetMethod("ParseSolution", BindingFlags.NonPublic | BindingFlags.Instance);
}
}
public List<SolutionProject> Projects { get; private set; }
public Solution(string solutionFileName)
{
if (s_SolutionParser == null)
{
throw new InvalidOperationException("Can not find type 'Microsoft.Build.Construction.SolutionParser' are you missing a assembly reference to 'Microsoft.Build.dll'?");
}
var solutionParser = s_SolutionParser.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).First().Invoke(null);
using (var streamReader = new StreamReader(solutionFileName))
{
s_SolutionParser_solutionReader.SetValue(solutionParser, streamReader, null);
s_SolutionParser_parseSolution.Invoke(solutionParser, null);
}
var projects = new List<SolutionProject>();
var array = (Array)s_SolutionParser_projects.GetValue(solutionParser, null);
for (int i = 0; i < array.Length; i++)
{
projects.Add(new SolutionProject(array.GetValue(i)));
}
this.Projects = projects;
}
}
[DebuggerDisplay("{ProjectName}, {RelativePath}, {ProjectGuid}")]
public class SolutionProject
{
static readonly Type s_ProjectInSolution;
static readonly PropertyInfo s_ProjectInSolution_ProjectName;
static readonly PropertyInfo s_ProjectInSolution_RelativePath;
static readonly PropertyInfo s_ProjectInSolution_ProjectGuid;
static readonly PropertyInfo s_ProjectInSolution_ProjectType;
static SolutionProject()
{
s_ProjectInSolution = Type.GetType("Microsoft.Build.Construction.ProjectInSolution, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false, false);
if (s_ProjectInSolution != null)
{
s_ProjectInSolution_ProjectName = s_ProjectInSolution.GetProperty("ProjectName", BindingFlags.NonPublic | BindingFlags.Instance);
s_ProjectInSolution_RelativePath = s_ProjectInSolution.GetProperty("RelativePath", BindingFlags.NonPublic | BindingFlags.Instance);
s_ProjectInSolution_ProjectGuid = s_ProjectInSolution.GetProperty("ProjectGuid", BindingFlags.NonPublic | BindingFlags.Instance);
s_ProjectInSolution_ProjectType = s_ProjectInSolution.GetProperty("ProjectType", BindingFlags.NonPublic | BindingFlags.Instance);
}
}
public string ProjectName { get; private set; }
public string RelativePath { get; private set; }
public string ProjectGuid { get; private set; }
public string ProjectType { get; private set; }
public SolutionProject(object solutionProject)
{
this.ProjectName = s_ProjectInSolution_ProjectName.GetValue(solutionProject, null) as string;
this.RelativePath = s_ProjectInSolution_RelativePath.GetValue(solutionProject, null) as string;
this.ProjectGuid = s_ProjectInSolution_ProjectGuid.GetValue(solutionProject, null) as string;
this.ProjectType = s_ProjectInSolution_ProjectType.GetValue(solutionProject, null).ToString();
}
}
Обратите внимание, что вы должны изменить целевую платформу на «.NET Framework 4» (не профиль клиента), чтобы иметь возможность добавить ссылку Microsoft.Build в свой проект.
SolutionFile
Microsoft.Build.dll появился новый общедоступный класс, который устанавливается вместе с Visual Studio 2015 (см. Msdn.microsoft.com/en-us/library/… )В Visual Studio 2015 теперь есть общедоступный
SolutionFile
класс, который можно использовать для анализа файлов решений:Этот класс находится в сборке Microsoft.Build.dll 14.0.0.0 . В моем случае он находился по адресу:
Спасибо Филу за указание на это !
источник
Add-Type -Path "C:\Program Files (x86)\Reference Assemblies\Microsoft\MSBuild\v14.0\Microsoft.Build.dll"
$slnFile = [Microsoft.Build.Construction.SolutionFile]::Parse($slnPath);
$slnFile.ProjectsInOrder
Я не знаю, ищет ли кто-нибудь еще решения этой проблемы, но я наткнулся на проект, который, кажется, делает именно то, что нужно. https://slntools.codeplex.com/ Одна из функций этого инструмента - объединить несколько решений вместе.
источник
JetBrains (создатели Resharper) имеют публичные возможности синтаксического анализа sln в своих сборках (отражение не требуется). Вероятно, он более надежен, чем предлагаемые здесь существующие решения с открытым исходным кодом (не говоря уже о хаках ReGex). Все, что вам нужно сделать, это:
JetBrains.Platform.ProjectModel
JetBrains.Platform.Util
JetBrains.Platform.Interop.WinApi
Библиотека не документирована, но Reflector (или действительно dotPeek) - ваш друг. Например:
источник
Я действительно не могу предложить вам библиотеку и полагаю, что ее не существует. Но я потратил много времени, возясь с файлами .sln в сценариях пакетного редактирования, и я обнаружил, что Powershell является очень полезным инструментом для этой задачи. Формат .SLN довольно прост и может быть почти полностью проанализирован с помощью нескольких быстрых и грязных выражений. Например
Включенные файлы проекта.
Это не всегда красиво, но это эффективный способ пакетной обработки.
источник
мы решили аналогичную проблему слияния решений автоматически, написав плагин Visual Studio, который создал новое решение, затем искал файл * .sln и импортировал его в новый, используя:
Наша проблема немного отличалась тем, что мы хотели, чтобы VS определил для нас порядок сборки, поэтому мы затем преобразовали все ссылки на dll в ссылки на проекты, где это возможно.
Затем мы автоматизировали это в процессе сборки, запустив VS через автоматизацию COM.
Это решение было немного Хита Робинсона, но имело то преимущество, что VS занимался редактированием, поэтому наш код не зависел от формата файла sln. Это было полезно, когда мы перешли с VS 2005 на 2008 и снова на 2010.
источник
Все отлично, но я также хотел получить возможность генерации sln - на снимке кода выше вы разбираете только файлы .sln - я хотел сделать аналогичную вещь, за исключением возможности повторно сгенерировать sln с небольшими изменениями обратно в файл .sln . Такими случаями может быть, например, перенос одного и того же проекта на другую платформу .NET. Пока это только повторная генерация sln, но позже я расширю ее и на проекты.
Думаю, я также хотел продемонстрировать мощь регулярных выражений и собственных интерфейсов. (Меньший объем кода с большей функциональностью)
Обновление 4.1.2017 Я создал отдельный репозиторий svn для разбора решения .sln: https://sourceforge.net/p/syncproj/code/HEAD/tree/
Ниже приведен фрагмент моего собственного кода (предшественник). Вы можете использовать любой из них.
Возможно, что в будущем код синтаксического анализа решений на основе svn также будет обновлен с возможностью генерации.Обновление 4.2.2017 Исходный код в SVN также поддерживает генерацию .sln.
источник
Я объяснил, определил, что классы MSBuild можно использовать для управления базовыми структурами. Позже у меня будет дополнительный код на моем веб-сайте.
источник
relativepath
становится URL-адресом, который сайт должен запускать в IISExpress и т.д.Ответ @ john-leidegren великолепен. Для версий до VS2015 это очень полезно. Но произошла небольшая ошибка, так как код для получения конфигураций отсутствовал. Поэтому хотел добавить его, на случай, если кто-то изо всех сил пытается использовать этот код.
Улучшение очень простое:
В качестве дополнительной помощи, предоставляя простой код для просмотра свойств объекта,
System.Type
предложенный @oasten.источник
Как бы то ни было, я создал небольшой проект для чтения файлов sln и proj, доступных на nuget:
https://www.nuget.org/packages/ByteDev.DotNet/
источник
Спасибо @John Leidegren, что он предлагает эффективный способ. Я пишу класс hlper, потому что не могу использовать его код, который не может найти
s_SolutionParser_configurations
проекты без FullName.Код находится в github, что позволяет получать проекты с FullName.
И код не может получить SolutionConfiguration.
Но когда вы разрабатываете vsx, vs скажет, что не могу найти
Microsoft.Build.dll
, поэтому вы можете попробовать использовать dte для получения всех проектов.Код, который использует dte для получения всех проектов, находится в github
источник