Visual Studio Protocol Handler - Open File
H

1

8

Does Visual Studio have a Protocol Handler that includes a command to open a specific file?

They have one for Git clone, as described in Announcing the GitHub Extension for Visual Studio:

The Open in Visual Studio button [in GitHub] calls a new protocol handler called “git-client://”. We designed this new generic protocol together with GitHub to allow a website pass standard Git operations to any IDE

Essentially what I want to do is described in this GitHub Issues:

enter image description here

When I click on the Button, Visual Studio should open the specific file (preferably with the correct Solution loaded as well).

If this isn't possible directly with Protocol Handlers, could it be done as a Visual Studio Extensions with a Web View that would achieve the same purpose (ie allow opening files from a Web Page)?

Herren answered 5/1, 2016 at 3:16 Comment(2)
As of Visual Studio 2017.6 and newer, this capability is now provided by Microsoft. github.com/microsoft/VSSDK-Extensibility-Samples/tree/master/…Christie
Look at that, Mads to the rescue!Herren
H
4

I was able to get close enough to what I wanted by creating a Visual Studio plugin with a self hosted Owin server exposing a basic WebApi.

This allowed me to open files from a browser with a link like: http://localhost:9000/VisualStudioApi/OpenFile?Path=.\Url\Escaped\Path\Relative\To\Solution\File

Opening files in Visual Studio via a web browser

Any web server hosting this button would need to hardcode the links to http://localhost:9000, which brings up an issue of having multiple Visual Studio instances running, so there would need to be some logic about how to map a .sln file to a known port. But absent an official Visual Studio solution, this gets the job done for the most part.


In case this helps someone in the future, here are the code snippets:

VS Package

[ComVisible(true)]
[Guid("B77F7C65-0F9F-422A-A897-C06FDAEC9604")]
[ProvideObject(typeof(InitializerPackage))]
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
public class InitializerPackage : Package
{
    protected override void Initialize()
    {
        base.Initialize();

        //Get copy of current DTE
        var dte = (DTE)GetService(typeof(DTE));
        var dte2 = dte as DTE2;

        dte2.Events.SolutionEvents.Opened += () => 
             OwinVisualStudioApiListenerManager.StartServer(dte2);
        dte2.Events.SolutionEvents.AfterClosing += () => 
             OwinVisualStudioApiListenerManager.StopServer();           
    }
}

Owin Initializer

public static class OwinVisualStudioApiListenerManager
{
    private static IDisposable _runningServer;

    public static DTE2 VisualStudioApi { get; set; }

    public static void StartServer(DTE2 visualStudioApi)
    {
        if (null != _runningServer)
            _runningServer.Dispose();

        VisualStudioApi = visualStudioApi;

        //nothing fancy about OwinStartup
        //see github file http://tinyurl.com/zt2bm8b
        _runningServer = WebApp.Start<OwinStartup>("http://localhost:9000");
    }

    public static void StopServer()
    {
        if (null != _runningServer)
            _runningServer.Dispose();

        VisualStudioApi = null;
    }
}

WebApi

public class VisualStudioApiController : ApiController
{
    // GET /VisualStudioApi/OpenFile/?path=
    [HttpGet]
    public string OpenFile(string path)
    {
         var fullPath = Path.Combine(
                Path.GetDirectoryName(
                    OwinVisualStudioApiListenerManager.VisualStudioApi.Solution.FullName),
                HttpUtility.UrlDecode(path));

          //https://mcmap.net/q/1471758/-how-to-open-file-programmatically-using-envdte-in-c/1224069
          OwinVisualStudioApiListenerManager.VisualStudioApi
                .ExecuteCommand(
                    "File.OpenFile",
                    fullPath);

           return "success";
    }
}
Herren answered 5/1, 2016 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.