Versi .NET 4.0 dari rakitan Microsoft.Build berisi kelas SolutionParser di ruang nama Microsoft.Build.Construction yang mem-parsing file solusi Visual Studio.
Sayangnya kelas ini bersifat internal, tetapi saya telah membungkus beberapa fungsionalitas itu di kelas yang menggunakan refleksi untuk mendapatkan beberapa properti umum yang mungkin berguna bagi Anda.
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();
}
}
Perhatikan bahwa Anda harus mengubah kerangka kerja target Anda ke ".NET Framework 4" (bukan profil klien) untuk dapat menambahkan referensi Microsoft.Build ke proyek Anda.
SolutionFile
diperkenalkan di Microsoft.Build.dll yang diinstal dengan Visual Studio 2015 (lihat msdn.microsoft.com/en-us/library/… )Dengan Visual Studio 2015 sekarang ada
SolutionFile
kelas yang dapat diakses publik yang dapat digunakan untuk mengurai file solusi:Kelas ini ditemukan di rakitan Microsoft.Build.dll 14.0.0.0 . Dalam kasus saya, itu terletak di:
Terima kasih kepada Phil karena telah menunjukkan hal ini !
sumber
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
Saya tidak tahu apakah ada yang masih mencari solusi untuk masalah ini, tetapi saya menemukan proyek yang tampaknya melakukan apa yang diperlukan. https://slntools.codeplex.com/ Salah satu fungsi alat ini adalah menggabungkan beberapa solusi bersama.
sumber
JetBrains (pencipta Resharper) memiliki kemampuan parsing sln publik di rakitan mereka (tidak perlu refleksi). Ini mungkin lebih kuat daripada solusi sumber terbuka yang ada yang disarankan di sini (apalagi peretasan ReGex). Yang perlu Anda lakukan hanyalah:
JetBrains.Platform.ProjectModel
JetBrains.Platform.Util
JetBrains.Platform.Interop.WinApi
Perpustakaan tidak didokumentasikan, tetapi Reflector (atau memang, dotPeek) adalah teman Anda. Sebagai contoh:
sumber
Saya tidak bisa benar-benar menawarkan Anda perpustakaan dan saya kira tidak ada perpustakaan yang ada di luar sana. Tapi saya telah menghabiskan banyak waktu bermain-main dengan file .sln dalam skenario pengeditan batch dan saya telah menemukan Powershell menjadi alat yang sangat berguna untuk tugas ini. Format .SLN cukup sederhana dan hampir dapat diurai seluruhnya dengan beberapa ekspresi cepat dan kotor. Sebagai contoh
File Proyek yang disertakan.
Ini tidak selalu cantik, tetapi ini adalah cara efektif untuk melakukan pemrosesan batch.
sumber
kami memecahkan masalah yang sama dalam menggabungkan solusi secara otomatis dengan menulis plugin Visual Studio yang membuat solusi baru kemudian mencari file * .sln dan mengimpornya ke yang baru menggunakan:
Masalah kami sedikit berbeda karena kami ingin VS memilah urutan pembuatan untuk kami, jadi kami kemudian mengonversi referensi dll apa pun ke referensi proyek jika memungkinkan.
Kami kemudian mengotomatiskan ini menjadi proses pembuatan dengan menjalankan VS melalui otomatisasi COM.
Solusi ini sedikit Heath Robinson, tetapi memiliki keuntungan bahwa VS melakukan pengeditan sehingga kode kami tidak bergantung pada format file sln. Yang sangat membantu ketika kami pindah dari VS 2005 ke 2008 dan sekali lagi ke 2010.
sumber
Semuanya bagus, tetapi saya juga ingin mendapatkan kemampuan pembuatan sln - dalam snapshot kode di atas Anda hanya mem-parsing file .sln - Saya ingin membuat hal serupa kecuali untuk dapat menghasilkan kembali sln dengan sedikit modifikasi kembali ke file .sln . Kasus seperti itu dapat menjadi contoh proyek yang sama untuk porting .NET platform yang berbeda. Untuk saat ini hanya sln re-generation, tapi nanti saya akan kembangkan ke project juga.
Saya rasa saya juga ingin mendemonstrasikan kekuatan ekspresi reguler dan antarmuka asli. (Jumlah kode lebih kecil dengan lebih banyak fungsi)
Pembaruan 4.1.2017 Saya telah membuat repositori svn terpisah untuk mem -parsing solusi .sln: https://sourceforge.net/p/syncproj/code/HEAD/tree/
Di bawah ini adalah cuplikan sampel kode saya sendiri (pendahulu). Anda bebas menggunakan salah satunya.
Ada kemungkinan bahwa di masa depan kode parsing solusi berbasis svn akan diperbarui dengan kemampuan generasi juga.Pembaruan 4.2.2017 Kode sumber di SVN mendukung pembuatan .sln juga.
sumber
Saya menjelaskan, menentukan bahwa kelas MSBuild dapat digunakan untuk memanipulasi struktur yang mendasarinya. Saya akan memiliki kode lebih lanjut di situs web saya nanti.
sumber
relativepath
menjadi URL situs yang harus dijalankan di IISExpress dll di bawah.Jawaban oleh @ john-leidegren bagus. Untuk pra-VS2015, ini sangat berguna. Tetapi ada kesalahan kecil, karena kode untuk mengambil konfigurasi hilang. Jadi ingin menambahkannya, jika seseorang kesulitan menggunakan kode ini.
Peningkatannya sangat sederhana:
Sebagai bantuan tambahan, menyediakan kode sederhana untuk menjelajahi properti a
System.Type
seperti yang disarankan oleh @oasten.sumber
Untuk apa nilainya sekarang saya telah membuat sebuah proyek kecil untuk membaca file sln dan proj yang tersedia di nuget:
https://www.nuget.org/packages/ByteDev.DotNet/
sumber
Terima kasih @John Leidegren dia menawarkan cara yang efektif. Saya menulis kelas hlper karena saya tidak dapat menggunakan kodenya yang tidak dapat menemukan
s_SolutionParser_configurations
dan proyek tanpa FullName.Kode ada di github yang bisa mendapatkan proyek dengan Nama Lengkap.
Dan kode tidak bisa mendapatkan SolutionConfiguration.
Tetapi ketika Anda mengembangkan vsx, vs akan mengatakan tidak dapat menemukan
Microsoft.Build.dll
, jadi Anda dapat mencoba menggunakan dte untuk mendapatkan semua proyek.Kode yang menggunakan dte untuk mendapatkan semua proyek ada di github
sumber