A lightweight toolkit for building Visual Studio extensions (VSIX). VsSharp wraps the
EnvDTE automation model and the VS Shell interop APIs behind a friendlier, strongly-typed
surface so you can focus on your extension's behavior instead of boilerplate.
Published on NuGet as VsSharp.
- Host — a singleton entry point that wires up DTE events (solution, document, startup,
shutdown) and exposes convenience accessors (
Solution,Windows,Statusbar, output window helpers, service resolution). - Command framework — declare buttons, menus and context menus in XML and have them built on the VS command bars at runtime, including nested sub-menus and dynamically generated menus.
- Dependency-driven enabling — show/enable commands based on context such as whether a solution, project, or document is open.
- Project & solution extensions — a rich set of
EnvDTE.Project/Solutionextension methods for references, project items, properties, package metadata, and more. - Document & window accessors — read/write the active document's text and manage tool windows.
- Visual Studio (extension development workload)
net472- The VS SDK is referenced via the
Microsoft.VisualStudio.SDKmetapackage
Install-Package VsSharpor via the .NET CLI:
dotnet add package VsSharpSet up the Host from your package's initialization. Assigning Host.Instance.DTE
automatically subscribes to the relevant DTE events.
using CnSharp.VisualStudio.Extensions;
using Microsoft.VisualStudio.Shell;
protected override async Task InitializeAsync(CancellationToken ct, IProgress<ServiceProgressData> progress)
{
await this.JoinableTaskFactory.SwitchToMainThreadAsync(ct);
var dte = (EnvDTE._DTE)await GetServiceAsync(typeof(EnvDTE._DTE));
Host.Instance.DTE = dte;
// optional lifecycle hooks
Host.Instance.SolutionOpenedAction = () => { /* ... */ };
Host.Instance.DocumentOpenedAction = doc => { /* ... */ };
}Commands are described by a CommandConfig and typically loaded from an embedded XML
resource. Each control points at a class implementing ICommand via its ClassName.
<root>
<resource>MyExtension.Resources.Strings</resource>
<buttons>
<button id="MyExtension.SayHello"
class="MyExtension.Commands.SayHelloCommand"
dependsOn="SolutionProject" />
</buttons>
<menus>
<menu id="MyExtension.TopMenu" caption="My Tools">
<menu id="MyExtension.Child" class="MyExtension.Commands.ChildCommand" />
</menu>
</menus>
</root>using CnSharp.VisualStudio.Extensions.Commands;
public class SayHelloCommand : ICommand
{
public void Execute(object args = null)
{
Host.Instance.WriteToOutputWindow("MyExtension", "Hello from VsSharp!");
}
}var plugin = new Plugin
{
Id = new Guid("..."),
Name = "MyExtension",
Assembly = typeof(MyPackage).Assembly,
CommandConfig = config // deserialized from the XML above
};
var manager = new CommandManager(plugin);
manager.Load(); // builds the command bar controls
// manager.Execute("MyExtension.SayHello");
// manager.Disconnect(); // tears the controls downCommands declared with a dependsOn value (for example SolutionProject or Document)
are automatically enabled or disabled as the corresponding context changes, via
CommandManager.ApplyDependencies.
ProjectExtensions adds many helpers on top of EnvDTE.Project:
string ns = project.GetRootNameSpace();
string dir = project.GetDirectory();
bool isSdkStyle = project.IsSdkBased();
bool isCore = project.IsNetCoreProject();
// references
project.AddReference("Newtonsoft.Json", @"C:\libs\Newtonsoft.Json.dll");
var refs = project.GetReferences();
// project items
project.AddFromFile(@"C:\path\file.cs");
project.AddFromFileAsLink(@"C:\shared\Common.cs", "Common.cs");
project.AddFolder("Generated");
// package metadata (NuGet PropertyGroup values)
PackageProjectProperties meta = project.GetPackageProjectProperties();
meta.Description = "Updated description";
List<string> failures = project.SavePackageProjectProperties(meta);| Type | Purpose |
|---|---|
Host |
Singleton entry point; DTE event wiring and shell convenience accessors. |
Plugin |
Describes an extension instance (id, assembly, command config, resources). |
CommandManager |
Builds, resets, executes and tears down command bar controls. |
CommandConfig / CommandMenu / CommandButton |
XML-serializable command definitions. |
ICommand |
Implemented by command handler classes. |
ICommandMenuGenerator |
Produces dynamically generated sub-menus. |
ProjectExtensions / SolutionExtensions |
EnvDTE automation helpers. |
IDocumentAccessor / IWindowAccessor / IToolWindowAccessor |
Document and window access. |
PackageProjectProperties / ProjectProperties |
Strongly-typed project/package metadata. |
MIT © CnSharp Studio. See the repository for details.
Project home: https://github.com/cnsharp/VS.Sharp