{"id":16974820,"url":"https://github.com/3f/mvssln","last_synced_at":"2025-05-15T19:04:03.261Z","repository":{"id":47563858,"uuid":"94708524","full_name":"3F/MvsSln","owner":"3F","description":"🧩 Customizable VisualStudio .sln parser with project support (.vcxproj, .csproj., …). Pluggable lightweight r/w handlers at runtime, and more …","archived":false,"fork":false,"pushed_at":"2024-10-27T23:13:59.000Z","size":2166,"stargazers_count":144,"open_issues_count":11,"forks_count":27,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-05-15T19:03:43.184Z","etag":null,"topics":["csproj","msbuild","mvssln","projectguid","sln","sln-files","sln-parser","vcxproj","visual-studio","visualstudio","vs","vs2010","vs2012","vs2013","vs2015","vs2017","vs2019","vs2022"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/3F.png","metadata":{"files":{"readme":"Readme.md","changelog":"changelog.txt","contributing":null,"funding":".github/FUNDING.yml","license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["3F.github.io/fund"]}},"created_at":"2017-06-18T19:30:20.000Z","updated_at":"2025-03-21T19:07:54.000Z","dependencies_parsed_at":"2022-09-12T12:24:23.747Z","dependency_job_id":"47cacc03-79c0-48fe-8be3-ce68618cdd85","html_url":"https://github.com/3F/MvsSln","commit_stats":{"total_commits":142,"total_committers":4,"mean_commits":35.5,"dds":0.5070422535211268,"last_synced_commit":"36a9194c40a2eae321c2035e64c8114df9125495"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FMvsSln","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FMvsSln/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FMvsSln/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FMvsSln/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/3F","download_url":"https://codeload.github.com/3F/MvsSln/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254404356,"owners_count":22065641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csproj","msbuild","mvssln","projectguid","sln","sln-files","sln-parser","vcxproj","visual-studio","visualstudio","vs","vs2010","vs2012","vs2013","vs2015","vs2017","vs2019","vs2022"],"created_at":"2024-10-14T01:08:18.868Z","updated_at":"2025-05-15T19:04:03.213Z","avatar_url":"https://github.com/3F.png","language":"C#","funding_links":["3F.github.io/fund"],"categories":[],"sub_categories":[],"readme":"[![](https://raw.githubusercontent.com/3F/MvsSln/master/MvsSln/Resources/MvsSln_v1_96px.png)](https://github.com/3F/MvsSln) [**MvsSln**](https://github.com/3F/MvsSln)\n\nCustomizable VisualStudio .sln parser with project support (.vcxproj, .csproj., …). Pluggable lightweight r/w handlers at runtime, and more …\n\n```r\nCopyright (c) 2013-2024  Denis Kuzmin \u003cx-3F@outlook.com\u003e github/3F\n```\n\n[ 「 ❤ 」 ](https://3F.github.io/fund) [![License](https://img.shields.io/badge/License-MIT-74A5C2.svg)](https://github.com/3F/MvsSln/blob/master/License.txt)\n\n[*MvsSln*](https://github.com/3F/MvsSln) is waiting for your awesome contributions! https://github.com/3F/MvsSln/graphs/contributors\n\n| Download    | Windows | Linux\n|-------------|---------|--------\n| [![NuGet](https://img.shields.io/nuget/v/MvsSln.svg)](https://www.nuget.org/packages/MvsSln/) \u003cbr/\u003e [`gnt MvsSln`](https://github.com/3F/GetNuTool#getnutool) | [![status](https://ci.appveyor.com/api/projects/status/6uunsds889rhkpo2/branch/master?svg=true)](https://ci.appveyor.com/project/3Fs/mvssln-fxjnf/branch/master) | [![status](https://ci.appveyor.com/api/projects/status/vdt3taxswrxo37tt/branch/master?svg=true)](https://ci.appveyor.com/project/3Fs/mvssln-2d2c2/branch/master)\n| [![release](https://img.shields.io/github/release/3F/MvsSln.svg)](https://github.com/3F/MvsSln/releases/latest) | [![Tests](https://img.shields.io/appveyor/tests/3Fs/mvssln-fxjnf/master.svg)](https://ci.appveyor.com/project/3Fs/mvssln-fxjnf/build/tests) | [![Tests](https://img.shields.io/appveyor/tests/3Fs/mvssln-2d2c2/master.svg)](https://ci.appveyor.com/project/3Fs/mvssln-2d2c2/build/tests)\n\n## Why MvsSln\n\nMvsSln provides the easiest way to complex work with Visual Studio .sln files and referenced projects (.vcxproj, .csproj., ...). Merge, Manage, Attach custom handlers and more. Because it's free, because it's open.\n\n🌌 The most convenient work with projects, dependencies, their lazy loading, any folders, any items, references and much more in these different worlds;\n\n💡 We are customizable and extensible library at runtime! Make **your custom** .sln and its parsing for everything you like at the moment you need just in a few steps;\n\n🚀 We were born from other popular project to be more loyal for your preferences on the fly. Hello from 2013;\n\nEven if you just need the basic access to information or more complex work through our readers and writers.\n\nCreate/modify/or just use parsed folders, projects, and other. \n\nSafely compare anything, \n\n```csharp\nif(new ProjectItem(...) == new ProjectItem(...)) { ... }\nif(new SolutionFolder(...) == new SolutionFolder(...)) { ... }\nif(new ConfigItem(...) == new ConfigItem(...)) { ... }\nif(new PackageInfo(...) == new PackageInfo(...)) { ... }\n...\n````\n\n\nUse 📂 Subdirectories,\n\n```csharp\nnew SolutionFolder(\"dir1\", \n    new SolutionFolder(\"dir2\", \n        new SolutionFolder(\"dir3\", \"hMSBuild.bat\", \"DllExport.bat\")\n    )\n);\n...\nnew SolutionFolder(\"{EE7DD6B7-56F4-478D-8745-3D204D915473}\", \"MyFolder2\", dir1, \".gnt\\\\gnt.core\");\n...\n```\n\nProjects and Folders,\n\n```csharp\nnew ProjectItem(\"Project1\", ProjectType.Cs);\nnew ProjectItem(\"Project1\", ProjectType.Cs, new SolutionFolder(\"dir1\"));\nnew ProjectItem(\"Project2\", ProjectType.Vc, \"path 1\");\nnew ProjectItem(\"{EE7DD6B7-56F4-478D-8745-3D204D915473}\", \"Project1\", ProjectType.Cs, dir2);\n...\n```\n\nDetect the real\\* project types,\n\n```csharp\n* IsCs() - Checking both legacy `ProjectType.Cs` and modern `ProjectType.CsSdk` types.\n. . .\n* IsSdk() - While ProjectType cannot inform the actual use of the modern Sdk style in projects,\n            current method will try to detect this by using the extended logic:\n            https://github.com/dotnet/project-system/blob/master/docs/opening-with-new-project-system.md\n```\n\nLoad only what is needed at the moment,\n\n```csharp\n// https://github.com/3F/MvsSln/discussions/49\n\nusing var sln = new Sln(\"Input.sln\", SlnItems.Env);\n\nsln.Result.Env\n    .LoadProjects(sln.Result.ProjectItemsConfigs.Where(p =\u003e p.project.IsCs()))\n    .ForEach(xp =\u003e\n    {\n        xp.AddItem(\"Compile\", @\"financial\\Invoice.cs\");\n    });\n```\n\nModify *.sln* at runtime,\n\nhttps://github.com/3F/MvsSln/discussions/43#discussioncomment-371185\n\n```csharp\n// new collection from available projects but without project 'UnLib'\nvar projects = sln.Result.ProjectItems.Where(p =\u003e p.name != \"UnLib\");\n\n// prepare write-handlers\nvar whandlers = new Dictionary\u003cType, HandlerValue\u003e() {\n    [typeof(LProject)] = new HandlerValue(new WProject(projects, sln.Result.ProjectDependencies)),\n};\n\n// save result\nusing(var w = new SlnWriter(@\"modified.sln\", whandlers)) {\n    w.Write(sln.Result.Map);\n}\n```\n\nManage [packages.config](https://github.com/3F/MvsSln/pull/30),\n\n```csharp\n// 2.6+\nusing Sln l = new(\"Input.sln\", SlnItems.AllNoLoad | SlnItems.PackagesConfig);\n\nIPackageInfo found = l.Result.PackagesConfigs\n                                .SelectMany(s =\u003e s.Packages)\n                                .FirstOrDefault(p =\u003e p.Id.StartsWith(\"Microsoft.\"));\n// found.MetaTFM ...\n\nVersion v = l.Result.PackagesConfigs.First().GetPackage(\"LX4Cnh\")?.VersionParsed;\n```\n\nEasily create files [from scratch](https://github.com/3F/MvsSln/wiki/Creating-from-scratch),\n\n```csharp\n// 2.7+\nLhDataHelper hdata = new();\nhdata.SetHeader(SlnHeader.MakeDefault())\n        .SetProjects(projects)\n        .SetProjectConfigs(prjConfs)\n        .SetSolutionConfigs(slnConf);\n\nusing(SlnWriter w = new(solutionFile, hdata))\n{\n    w.Options = SlnWriterOptions.CreateProjectsIfNotExist;\n    w.Write();\n}\n\nusing Sln sln = new(solutionFile, SlnItems.EnvWithMinimalProjects);\nIXProject xp = sln.Result.Env.Projects.First();\n\nxp.SetProperties(new Dictionary\u003cstring, string\u003e()\n{\n    { \"OutputType\", \"EXE\" },\n    { \"TargetFramework\", \"net8.0\" },\n    { \"Platforms\", \"x64\" }\n});\nxp.Save();\n```\n\nEverything at hand,\n\n```csharp\nusing(var sln = new Sln(@\"D:\\projects\\Conari\\Conari.sln\", SlnItems.All \u0026 ~SlnItems.ProjectDependencies))\n{\n    //sln.Result.Env.XProjectByGuid(\n    //    sln.Result.ProjectDependencies.FirstBy(BuildType.Rebuild).pGuid,\n    //    new ConfigItem(\"Debug\", \"Any CPU\")\n    //);\n\n    var p = sln.Result.Env.GetOrLoadProject(\n        sln.ProjectItems.FirstOrDefault(p =\u003e p.name == name)\n    );\n\n    var paths = sln.Result.ProjectItems\n                            .Select(p =\u003e new { p.pGuid, p.fullPath })\n                            .ToDictionary(p =\u003e p.pGuid, p =\u003e p.fullPath);\n\n    // {[{27152FD4-7B94-4AF0-A7ED-BE7E7A196D57}, D:\\projects\\Conari\\Conari\\Conari.csproj]}\n    // {[{0AEEC49E-07A5-4A55-9673-9346C3A7BC03}, D:\\projects\\Conari\\ConariTest\\ConariTest.csproj]}\n\n    foreach(IXProject xp in sln.Result.Env.Projects)\n    {\n        xp.AddReference(typeof(JsonConverter).Assembly, true);\n        xp.AddReference(\"System.Core\");\n\n        ProjectItem prj = ...\n        xp.AddProjectReference(prj);\n\n        xp.AddImport(\"../packages/DllExport.1.5.1/tools/net.r_eg.DllExport.targets\", true);\n\n        xp.SetProperty(\"JsonConverter\", \"30ad4fe6b2a6aeed\", \"'$(Configuration)' == 'Debug'\");\n        xp.SetProperties\n        (\n            new[]\n            {\n                new PropertyItem(\"IsCrossTargetingBuild\", \"true\"),\n                new PropertyItem(\"CSharpTargetsPath\", \"$(MSBToolsLocal)\\\\CrossTargeting.targets\")\n            },\n            \"!Exists('$(MSBuildToolsPath)\\\\Microsoft.CSharp.targets')\"\n        );\n        // ...\n    }\n\n    sln.Result.ProjectConfigs.Where(c =\u003e c.Sln.Configuration == \"Debug\"); // project-cfgs by solution-cfgs\n    // ...\n\n} // release all loaded projects\n```\n\nAnd something more,\n\n```csharp\n// https://github.com/3F/MvsSln/discussions/42\n\nusing var sln = new Sln(\"TestStruct.sln\", SlnItems.Env);\n//...\nsln.Result.Env.Projects.ForEach(xp =\u003e \n    xp.Project.Xml.PropertyGroups.Where(p =\u003e p.Condition.Contains(\"'$(Configuration)|$(Platform)'\"))\n    .Where(p =\u003e\n        sln.Result.ProjectItemsConfigs.All(s =\u003e \n            !p.Condition.Contains($\"'{s.projectConfig.ConfigurationByRule}|{s.projectConfig.PlatformByRule}'\")\n        )\n    ).ForEach(p =\u003e p.Parent?.RemoveChild(p))\n);\n```\n\nThe any new solution handler (reader or writer) can be easily added because of our flexible architecture.\n\nControl anything and have fun !\n\n\u003e MvsSln was specially extracted and re-licensed from *vsSolutionBuildEvent* projects (GPL -\u003e MIT) for https://github.com/3F/DllExport and others! Join us 🎈\n\n## High quality Project Icons. Visual Studio\n\nSince Microsoft officially distributes [5,000 high quality free icons and bitmaps](https://twitter.com/GitHub3F/status/1219348325729816578) from products like Visual Studio,\n\nYou can also use related project icons together with MvsSln like it was already for .NET DllExport project:\n\n![](https://github.com/3F/MvsSln/blob/master/resources/DllExport_1.7.png?raw=true)\n\nFollow License Terms for icons and Find implementation in original repo: [https://github.com/3F/DllExport](https://github.com/3F/DllExport)\n\n## How or Where is used\n\nLet's consider examples of use in real projects below.\n\n### .NET DllExport\n\nDllExport project finally changed distribution of the packages starting with v1.6 release. The final manager now fully works via MvsSln:\n\n* https://github.com/3F/DllExport/wiki/DllExport-Manager\n\n![](https://raw.githubusercontent.com/3F/MvsSln/master/resources/MvsSln_DllExport_example.png)\n\nMvsSln also is **a core logic** in *Post-Processing* feature [[?]](https://github.com/3F/DllExport/pull/148)\n\n![](https://github.com/3F/MvsSln/blob/master/resources/MvsSln_and_DllExport_PostProc.png?raw=true)\n\n### vsSolutionBuildEvent\n\nvsSolutionBuildEvent now is completely integrated with MvsSln [[?](https://github.com/3F/vsSolutionBuildEvent/pull/53)]\n\nFully removed original parser and replaced related processing from Environment/IsolatedEnv/MSBuild/CIM. Now it just calls the corresponding modern methods from MvsSln.\n\nhttps://github.com/3F/vsSolutionBuildEvent\n\n![](https://github.com/3F/MvsSln/blob/master/resources/vsSBE_and_MvsSln.png?raw=true)\n\n![](https://github.com/3F/MvsSln/blob/master/resources/vsSBE_and_MvsSln_VS.png?raw=true)\n\n\n## Map \u0026 handlers\n\n2.0+ can optionally provide a [map of the analyzed data](https://github.com/3F/MvsSln/wiki/SlnWriter#about-skeleton-and-map). To enable this, define a [0x0080 bit](https://github.com/3F/MvsSln/blob/a00e3b341bbddc559a5af618e4a6e520b7bbb2d6/MvsSln/SlnItems.cs#L92).\n\nMvsSln's parser will fill the map using handlers that processed line and/or raw access through wrapper, like:\n\n[![](https://raw.githubusercontent.com/3F/MvsSln/master/resources/MvsSln_v2.0_Map.png)](https://github.com/3F/MvsSln/wiki/SlnWriter#about-skeleton-and-map)\n\nThe map may be used for any modifications or creating a new solution or project files through other handlers etc. \n\nRead more about map, skeleton, and *SlnWriter* [**here**](https://github.com/3F/MvsSln/wiki/SlnWriter)\n\n## Projects. Adding References\n\n```csharp\nXProject.AddPackageReference(\"Conari\", \"1.5.0\");\n```\n\n```csharp\nxp.AddProjectReference(projects.First());\nxp.AddProjectReference(new ProjectItem(ProjectType.Cs, @$\"{projName}\\src.csproj\"));\n```\n\n```csharp\nxp.AddReference(Assembly.GetExecutingAssembly());\n```\n\n```csharp\nXProject.AddReference(\"DllExport\", lib, AddReferenceOptions.MakeRelativePath);\n```\n\n```csharp\nxp.AddReference(\n    pathToDll,\n    AddReferenceOptions.DefaultResolve | AddReferenceOptions.OmitVersion | AddReferenceOptions.HidePrivate\n);\n```\n\n```xml\n\u003cReference Include=\"MvsSln, PublicKeyToken=4bbd2ef743db151e\" /\u003e\n```\n\n```xml\n\u003cReference Include=\"DllExport, Version=1.6.4.15293, Culture=neutral, PublicKeyToken=8337224c9ad9e356\"\u003e\n  \u003cHintPath\u003e..\\packages\\DllExport.1.6.4\\gcache\\metalib\\DllExport.dll\u003c/HintPath\u003e\n  \u003cPrivate\u003eFalse\u003c/Private\u003e\n\u003c/Reference\u003e\n```\n\n## Example of extending (your custom handlers)\n\nExample of `LProject` handler (**reader**):\n\n```csharp\nusing static net.r_eg.MvsSln.Core.Keywords;\n\npublic class LProject: LAbstract, ISlnHandler\n{\n    public override ICollection\u003cType\u003e CoHandlers { get; protected set; }\n        = [typeof(LProjectDependencies)];\n\n    public override bool IsActivated(ISvc svc)\n        =\u003e (svc.Sln.ResultType \u0026 SlnItems.Projects) == SlnItems.Projects;\n\n    public override bool Condition(RawText line)\n        =\u003e line.trimmed.StartsWith(Project_, StringComparison.Ordinal);\n\n    public override bool Positioned(ISvc svc, RawText line)\n    {\n        ProjectItem pItem = GetProjectItem(line.trimmed, svc.Sln.SolutionDir);\n        if(pItem.pGuid == null) return false;\n        if(svc.Sln.ProjectItemList == null) svc.Sln.ProjectItemList = [];\n\n        svc.Sln.ProjectItemList.Add(pItem);\n        return true;\n    }\n}\n```\n\nExample of `WSolutionConfigurationPlatforms` handler (**writer**):\n\n```csharp\nusing static net.r_eg.MvsSln.Core.Keywords;\n\npublic class WSolutionConfigurationPlatforms(IEnumerable\u003cIConfPlatform\u003e configs)\n    : WAbstract, IObjHandler\n{\n    protected IEnumerable\u003cIConfPlatform\u003e configs = configs;\n\n    public override string Extract(object data)\n    {\n        if(configs == null) return null;\n\n        lbuilder.Clear();\n        lbuilder.AppendLv1Line(SolutionConfigurationPlatformsPreSolution);\n\n        configs.ForEach(cfg =\u003e lbuilder.AppendLv2Line($\"{cfg} = {cfg}\"));\n\n        return lbuilder.AppendLv1(EndGlobalSection).ToString();\n    }\n}\n```\n\n## Build MvsSln from source\n\n```bat\ngit clone https://github.com/3F/MvsSln.git MvsSln\ncd MvsSln\n```\n\n### Windows. Visual Studio / MSBuild\n\n```bat\n.\\build Release\n```\nor together with configured [netfx4sdk](https://github.com/3F/netfx4sdk)\n\n```bat\n.\\build-CI Release\n```\n\n### Ubuntu. vscode / dotnet\n\n```sh\ndotnet build -c Release\n```\n\n### run unit tests\n\n```sh\ndotnet test -c Release --no-build --no-restore\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3f%2Fmvssln","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F3f%2Fmvssln","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3f%2Fmvssln/lists"}