• Stars
    star
    132
  • Rank 268,327 (Top 6 %)
  • Language
    C#
  • License
    MIT License
  • Created about 7 years ago
  • Updated 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🧩 Customizable VisualStudio .sln parser with project support (.vcxproj, .csproj., …). Pluggable lightweight r/w handlers at runtime, and more …

MvsSln

Customizable VisualStudio .sln parser, Complex support of the projects (.vcxproj, .csproj., …), Pluginable lightweight r/w handlers at runtime, and more … 🧩

Copyright (c) 2013-2022  Denis Kuzmin <x-3F@outlook.com> github/3F

@ License

MvsSln contributors https://github.com/3F/MvsSln/graphs/contributors

We're waiting for your awesome contributions!

Releases Windows Linux
📦 NuGet status status
release Tests

Build history

Why MvsSln ?

MvsSln 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.

🌌 The most convenient work with projects, dependencies, their lazy loading, any folders, any items, references and much more in these different worlds;

💡 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;

🚀 We were born from other popular project to be more loyal for your preferences on the fly. Hello from 2013;

Even if you just need the basic access to information or more complex work through our readers and writers.

Create/modify/or just use parsed folders, projects, and other.

Safely compare anything,

if(new ProjectItem(...) == new ProjectItem(...)) { ... }
if(new SolutionFolder(...) == new SolutionFolder(...)) { ... }
if(new RawText(...) == new RawText(...)) { ... }
if(new ConfigItem(...) == new ConfigItem(...)) { ... }
if(new PackageInfo(...) == new PackageInfo(...)) { ... }

Use 📂 Subdirectories,

new SolutionFolder("dir1", 
    new SolutionFolder("dir2", 
        new SolutionFolder("dir3", "hMSBuild.bat", "DllExport.bat")
    )
);
...
new SolutionFolder("{EE7DD6B7-56F4-478D-8745-3D204D915473}", "MyFolder2", dir1, ".gnt\\gnt.core");
...

Projects and Folders,

new ProjectItem("Project1", ProjectType.Cs);
new ProjectItem("Project1", ProjectType.Cs, new SolutionFolder("dir1"));
new ProjectItem("Project2", ProjectType.Vc, "path 1");
new ProjectItem("{EE7DD6B7-56F4-478D-8745-3D204D915473}", "Project1", ProjectType.Cs, dir2);
...

Detect the real* project types,

* IsCs() - Checking both legacy `ProjectType.Cs` and modern `ProjectType.CsSdk` types.
. . .
* IsSdk() - While ProjectType cannot inform the actual use of the modern Sdk style in projects,
            current method will try to detect this by using the extended logic:
            https://github.com/dotnet/project-system/blob/master/docs/opening-with-new-project-system.md

Load only what is needed at the moment,

// https://github.com/3F/MvsSln/discussions/49

using var sln = new Sln("Input.sln", SlnItems.Env);

sln.Result.Env
    .LoadProjects(sln.Result.ProjectItemsConfigs.Where(p => p.project.IsCs()))
    .ForEach(xp =>
    {
        xp.AddItem("Compile", @"financial\Invoice.cs");
    });

Modify .sln at runtime,

#43 (comment)

// new collection from available projects but without project 'UnLib'
var projects = sln.Result.ProjectItems.Where(p => p.name != "UnLib");

// prepare write-handlers
var whandlers = new Dictionary<Type, HandlerValue>() {
    [typeof(LProject)] = new HandlerValue(new WProject(projects, sln.Result.ProjectDependencies)),
};

// save result
using(var w = new SlnWriter(@"modified.sln", whandlers)) {
    w.Write(sln.Result.Map);
}

Manage packages.config,

// 2.6+
using Sln l = new("Input.sln", SlnItems.AllNoLoad | SlnItems.PackagesConfig);

IPackageInfo found = l.Result.PackagesConfigs
                                .SelectMany(s => s.Packages)
                                .FirstOrDefault(p => p.Id.StartsWith("Microsoft."));
// found.MetaTFM ...

Version v = l.Result.PackagesConfigs.First().GetPackage("LX4Cnh")?.VersionParsed;

Everything at hand,

using(var sln = new Sln(@"D:\projects\Conari\Conari.sln", SlnItems.All & ~SlnItems.ProjectDependencies))
{
    //sln.Result.Env.XProjectByGuid(
    //    sln.Result.ProjectDependencies.FirstBy(BuildType.Rebuild).pGuid,
    //    new ConfigItem("Debug", "Any CPU")
    //);

    var p = sln.Result.Env.GetOrLoadProject(
        sln.ProjectItems.FirstOrDefault(p => p.name == name)
    );

    var paths = sln.Result.ProjectItems
                            .Select(p => new { p.pGuid, p.fullPath })
                            .ToDictionary(p => p.pGuid, p => p.fullPath);

    // {[{27152FD4-7B94-4AF0-A7ED-BE7E7A196D57}, D:\projects\Conari\Conari\Conari.csproj]}
    // {[{0AEEC49E-07A5-4A55-9673-9346C3A7BC03}, D:\projects\Conari\ConariTest\ConariTest.csproj]}

    foreach(IXProject xp in sln.Result.Env.Projects)
    {
        xp.AddReference(typeof(JsonConverter).Assembly, true);
        xp.AddReference("System.Core");

        ProjectItem prj = ...
        xp.AddProjectReference(prj);

        xp.AddImport("../packages/DllExport.1.5.1/tools/net.r_eg.DllExport.targets", true);

        xp.SetProperty("JsonConverter", "30ad4fe6b2a6aeed", "'$(Configuration)' == 'Debug'");
        xp.SetProperties
        (
            new[]
            {
                new PropertyItem("IsCrossTargetingBuild", "true"),
                new PropertyItem("CSharpTargetsPath", "$(MSBToolsLocal)\\CrossTargeting.targets")
            },
            "!Exists('$(MSBuildToolsPath)\\Microsoft.CSharp.targets')"
        );
        // ...
    }

    sln.Result.ProjectConfigs.Where(c => c.Sln.Configuration == "Debug"); // project-cfgs by solution-cfgs
    // ...

} // release all loaded projects

And something more,

// https://github.com/3F/MvsSln/discussions/42

using var sln = new Sln("TestStruct.sln", SlnItems.Env);
//...
sln.Result.Env.Projects.ForEach(xp => 
    xp.Project.Xml.PropertyGroups.Where(p => p.Condition.Contains("'$(Configuration)|$(Platform)'"))
    .Where(p =>
        sln.Result.ProjectItemsConfigs.All(s => 
            !p.Condition.Contains($"'{s.projectConfig.ConfigurationByRule}|{s.projectConfig.PlatformByRule}'")
        )
    ).ForEach(p => p.Parent?.RemoveChild(p))
);

The any new solution handler (reader or writer) can be easily added because of our flexible architecture.

Control anything and have fun !

MvsSln was specially extracted and re-licensed from vsSolutionBuildEvent projects (GPL -> MIT) for https://github.com/3F/DllExport and others! Join us 🎈

High quality Project Icons. Visual Studio

Since Microsoft officially distributes 5,000 high quality free icons and bitmaps from products like Visual Studio,

You can also use related project icons together with MvsSln like it was already for .NET DllExport project:

Follow License Terms for icons and Find implementation in original repo: https://github.com/3F/DllExport

How or Where is used

Let's consider examples of use in real projects below.

.NET DllExport

DllExport project finally changed distribution of the packages starting with v1.6 release. The final manager now fully works via MvsSln:

MvsSln also is a core logic in Post-Processing feature [?]

vsSolutionBuildEvent

vsSolutionBuildEvent now is completely integrated with MvsSln [?]

Fully removed original parser and replaced related processing from Environment/IsolatedEnv/MSBuild/CIM. Now it just contains lightweight invoking of relevant methods.

https://github.com/3F/vsSolutionBuildEvent

Map of .sln & Writers

v2+ now also may provide map of analyzed data. To enable this, define a bit 0x0080 for type of operations to parser.

Parser will expose map through list of ISection for each line. For example:

  • Each section contains handler which processes this line + simple access via RawText if not.
  • All this may be overloaded by any custom handlers (readers - ISlnHandler) if it's required by your environment.

This map may be used for modification / define new .sln data through writers (IObjHandler). For example:

var data = new List<IConfPlatform>() {
    new ConfigSln("Debug", "Any CPU"),
    new ConfigSln("Release_net45", "x64"),
    new ConfigSln("Release", "Any CPU"),
};

var whandlers = new Dictionary<Type, HandlerValue>() {
    [typeof(LSolutionConfigurationPlatforms)] = new HandlerValue(new WSolutionConfigurationPlatforms(data)),
};

using(var w = new SlnWriter("<path_to>.sln", whandlers)) {
    w.Write(map);
}

Did you know

Projects

The 1 project instance means only the 1 project with specific configuration. That is, you should work with each instance separately if some project has 2 or more configurations:

First instance of project {4F8BB8CD-1116-4F07-9B8F-06D69FB8589B} with configuration 'Release_net45|Any CPU' that's related with solution cfg -> CI_Release_net45|Any CPU
Second instance of project {4F8BB8CD-1116-4F07-9B8F-06D69FB8589B} with configuration 'Debug|Any CPU' that's related with solution cfg -> Debug|Any CPU
...

For example, the vsSolutionBuildEvent contains 10 projects and 8 solution configurations:

DBG_SDK10; DBG_SDK15; DCI_SDK10; DCI_SDK15; REL_SDK10; REL_SDK15; RCI_SDK10; RCI_SDK15

Maximum possible configurations for each projects above should be calculated as 10 * 8 = 80, ie. 80 instances that can be loaded as each different project. EnvWithProjects will try load all available, but in fact, mostly 2 or more project-configuration can be related to the same 1 solution-configuration, therefore it can be just 30 or even 20 in reality, and so on.

However, if you need to work only with common data of specified project:

  • Just use any available configuration. That is, to load projects only with specific configuration, use for example IEnvironment.LoadProjects.
// SlnItems.Env will initialize environment without loading projects.
using(var sln = new Sln(@"vsSolutionBuildEvent.sln", SlnItems.Env))
{
    ISlnResult data         = sln.Result;
    IConfPlatform slnCfg    = data.SolutionConfigs.FirstOrDefault(); // to get first available solution configuration
    data.Env.LoadProjects(
        // prepare final list of projects that should be loaded
        data.ProjectItemsConfigs.Where(p => p.solutionConfig == slnCfg)
    );    
    //... data.Env.Projects will contain instances only for Where(p => p.solutionConfig == slnCfg) i.e. 8 in total
}

For modern versions also available IEnvironment.LoadMinimalProjects or EnvWithMinimalProjects flag.

Adding Reference & Assembly name

XProject.AddReference(lib, false);
<Reference Include="DllExport, Version=1.6.4.15293, Culture=neutral, PublicKeyToken=8337224c9ad9e356">
  <HintPath>..\packages\DllExport.1.6.4\gcache\metalib\DllExport.dll</HintPath>
  <Private>False</Private>
</Reference>
XProject.AddReference("DllExport", lib, false);
<Reference Include="DllExport">
  <HintPath>..\packages\DllExport.1.6.4\gcache\metalib\DllExport.dll</HintPath>
  <Private>False</Private>
</Reference>

You can also specify it via System.Reflection.Assembly etc.

Example of extending (your custom handlers)

Example of LProject handler (reader):

public class LProject: LAbstract, ISlnHandler
{
    public override bool IsActivated(ISvc svc)
    {
        return ((svc.Sln.ResultType & SlnItems.Projects) == SlnItems.Projects);
    }

    public override bool Condition(RawText line)
    {
        return line.trimmed.StartsWith("Project(", StringComparison.Ordinal);
    }

    public override bool Positioned(ISvc svc, RawText line)
    {
        var pItem = GetProjectItem(line.trimmed, svc.Sln.SolutionDir);
        if(pItem.pGuid == null) {
            return false;
        }

        if(svc.Sln.ProjectItemList == null) {
            svc.Sln.ProjectItemList = new List<ProjectItem>();
        }

        svc.Sln.ProjectItemList.Add(pItem);
        return true;
    }
}

Example of WSolutionConfigurationPlatforms handler (writer):

public class WSolutionConfigurationPlatforms: WAbstract, IObjHandler
{
    protected IEnumerable<IConfPlatform> configs;

    public override string Extract(object data)
    {
        var sb = new StringBuilder();

        sb.AppendLine($"{SP}GlobalSection(SolutionConfigurationPlatforms) = preSolution");

        configs.ForEach(cfg => sb.AppendLine($"{SP}{SP}{cfg} = {cfg}"));

        sb.Append($"{SP}EndGlobalSection");

        return sb.ToString();
    }

    public WSolutionConfigurationPlatforms(IEnumerable<IConfPlatform> configs)
    {
        this.configs = configs ?? throw new ArgumentNullException();
    }
}

How to get MvsSln

More Repositories

1

DllExport

.NET DllExport with .NET Core support (aka 3F/DllExport aka DllExport.bat)
C#
923
star
2

Conari

🧬 One-touch unmanaged memory, runtime dynamic use of the unmanaged native C/C++ in .NET world, related P/Invoke features, and …
C#
244
star
3

vsSolutionBuildEvent

🎛 Event-Catcher with variety of advanced Actions to service projects, libraries, build processes, runtime environment of the Visual Studio, MSBuild Tools, and …
C#
76
star
4

aml_s905_uboot

u-boot DDR mods ~
C
65
star
5

LuNari

🗦🌔 Lua for .NET :: Lua 5.4, 5.3, 5.2, 5.1, ...
C#
50
star
6

netfx4sdk

Developer Pack (SDK). NETFX 4: Visual Studio 2022 / MSBuild 17 / or other modern tools
Batchfile
33
star
7

Examples

An complete examples and related support for various popular projects, and more.
C++
27
star
8

GetNuTool

Embeddable Package Manager (+core in .bat); 🕊 Lightweight tool to Create or Distribute using basic shell scripts (no powershell no dotnet-cli)
Batchfile
27
star
9

regXwild

⏱ Superfast ^Advanced wildcards++? | Unique algorithms that was implemented on native unmanaged C++ but easily accessible in .NET via Conari (with caching of 0x29 opcodes +optimizations) etc.
C++
26
star
10

vsCommandEvent

Extending Visual Studio on the fly via E-MSBuild, SobaScript, C#, ...
C#
19
star
11

hMSBuild

.bat scripts with full Package Manager inside for searching and wrapping MSBuild tools. All Visual Studio and .NET Framework versions
Batchfile
19
star
12

IeXod

The most portable alternative to Microsoft.Build for evaluating, manipulating, and other progressive data processing in a compatible XML-like syntax
C#
16
star
13

Huid

🎫 High-speed a FNV-1a-128 hash-based UUID.
C#
16
star
14

7z.Libs

📦📦 🗜 An automated build of the `7z.Libs` NuGet packages.
Batchfile
13
star
15

UnmanagedEmitCalli

A tiny hack of the System.Private.CoreLib to provide an Unmanaged EmitCalli implementation at the .NET Standard 2.0 layer.
C#
10
star
16

TmVTweaks

A variety of patches and tweaks for TeamViewer software such as a completely hidden ugly toolbar, screen fixes, hotkeys, etc.
C#
6
star
17

LX4Cnh

Algorithm for high-speed multiplication of LARGE numbers
C#
6
star
18

sandbox

:: ⛱ Experimental or incomplete components and libraries or tests for different languages, frameworks, components, platforms, etc.
C++
6
star
19

GhrMeter.user.js

📊📈 Displays statistics for attachments on GitHub Releases page
JavaScript
3
star
20

E-MSBuild

Advanced Evaluator of MSBuild scripts with user-variables support through Varhead and more
C#
3
star
21

Fnv1a128

FNV-1a 「 128-bit 」 High-Speed implementations 🚀 using LX4Cnh etc.
C#
3
star
22

SobaScript

Extensible Modular Scripting Programming Language -- #SobaScript
C#
2
star
23

CI.MSBuild.Demo

[Archived] Samples with native C++ and .NET (CLR) projects for work with CI.MSBuild / vsSolutionBuildEvent. Has been moved to here →: https://github.com/3F/Examples
C#
1
star
24

MoConTool

A variety of patches and tweaks for your favorite mouse.
C#
1
star
25

3F

1
star
26

FlightSDCpp

FlightSDC++ project - client for Direct Connect protocol
C++
1
star
27

N7z

[ planned ] 7-Zip file archiver for .NET via github.com/3F/Conari
Batchfile
1
star
28

FlightSDC.RPC-WebSockets

RPC-WebSockets variant of flightSDC project - migrated from my public repository on Bitbucket
C++
1
star
29

3F.github.io

HTML
1
star
30

mos3sms-smsb

mos3sms - SMSb (plugin for moservices 3) - migrated from my public repository on Bitbucket
PHP
1
star
31

web.vsSBE

To support the vsSolutionBuildEvent / `_doc` folder has been imported from - bitbucket.org/3F/vssolutionbuildevent/wiki/
CSS
1
star
32

Jt

Extremely Small, Fast, and damn Customizable ⚙ template engine on Native low-level implementation. / Mr. Jt / [ TypeScript & JavaScript ]
JavaScript
1
star