Skip to content

Packaging a VS Code Debug Adapter For Use in VS

Andrew Crawley edited this page Feb 14, 2018 · 3 revisions

Walkthrough: Packaging a VS Code Debug Adapter For Use in VS

This walkthrough details the steps necessary to bring a Node-based VS Code debug adapter into VS. We’ll be using VS Code’s "mock debug" extension as a starting point, and detailing the steps necessary to package it for use in VS via the Debug Adapter Host.

Note that if your extension also contains a language service, it can also be packaged for use in VS - see Adding a Language Server Protocol extension.

Prerequisites

Your development machine will need the following installed:

Set up the "Debug Adapter Host" repo

This repository contains samples and utilities related to the VS Debug Adapter Host, including a C#-based sample debug adapter that demonstrates some of the more advanced features of the Debug Adapter Host, and a launcher extension for VS that simplifies the process of launching a debug adapter for testing.

Clone and build the repo

git clone https://github.com/Microsoft/VSDebugAdapterHost.git

Open and build the solution "VSDebugAdapterHost\src\VSDebugAdapterHostSamples.sln" in Visual Studio. This will install the Debug Adapter Launcher extension and other necessary tools.

Set up the "Mock Debug" repo

This repository contains a Node-based sample debugger extension provided by the VS Code team.

NOTE: Due to a bug (issue #2) in the Debug Adapter Host, we'll be using a custom patched version of the Mock Debug adapter. Once this issue is fixed in a future release of VS, we'll be able to use the Mock Debug adapter directly from VS Code.

Clone and build the repo

First, we need to clone the repository and build the extension.

git clone https://github.com/andrewcrawley/vscode-mock-debug.git
cd vscode-mock-debug
npm install
npm run-script compile

Identify the debug adapter files

Next, we need to identify the files that are part of the debug adapter. The "vsce" tool can be used to determine the set of files that would be distributed as part of the VS Code extension:

npm install –g vsce 
vsce ls

However, an extension generally contains other code and files that are not part of the debug adapter, which we can ignore for now. In the case of the Mock Debug extension, the only files necessary for running the debug adapter are:

out\mockDebug.js 
out\mockRuntime.js 
node_modules\vscode-debugadapter\package.json 
node_modules\vscode-debugadapter\lib\*.js 

Create the MockDebugAdapter project

The MockDebugAdapter project will produce a VSIX extension package that can be installed in VS.

Ensure the necessary dependencies are installed

In order to produce a VSIX, the "Visual Studio extension development" workload must be installed. Since the Mock Debug adapter is based on Node.js, the "Runtime for components based on Node.js v7.4.0 (x86)" component must be installed as well:

Selecting the "Visual Studio extension development" workload Selecting the "Runtime for components based on Node.js v7.4.0 (x86)" component

Create the VSIX project

Create an empty VSIX project by navigating to File -> New -> Project, then select Visual C# -> Extensibility -> VSIX Project.

"New Project" dialog showing "VSIX Project" selected

Define VSIX prerequisites

Since the Mock Debug adapter is based on Node.js, we need to make sure the Node.js runtime is installed along with our extension. Rather than bundling our own copy of "node.exe", we can rely on the VS Installer to provide it for us.

Double-click the "source.extension.vsixmanifest" file in the root of the project to open the manifest designer, then select the Prerequisites tab.

Click New, then configure the new prerequisite as shown and click OK:

"Add New Prerequisite" dialog, showing "Runtime for components based on Node.js v7.4.0 (x86)" selected as a prerequisite with a version of "[15.6,16.0)"

Add adapter files to the project

Create a project folder named "adapter" and copy all the adapter files we identified earlier into it, maintaining the original directory structure.

Be sure that all the files have their Build Action set to Content, and Include in VSIX set to True:

Solution Explorer, showing all adapter files selected and the "Build Action" and "Include in VSIX" properties set as described in the text.

Create a pkgdef for the adapter

A pkgdef file contains information that registers an extension with various components in VS. It serves much the same purpose as the "package.json" file used by VS Code. We’ll be using the file to register our new Mock Debugger engine.

Create a new file named "MockDebugAdapter.pkgdef" in the root of the project. Ensure that its Build Action is set to Content, and Include in VSIX is set to True.

Generate a new GUID as a unique identifier for the new engine. VS has a built-in tool that is very useful for this – click Tools -> Create GUID, ensure that the GUID Format is set to Registry Format, then click Copy to copy the new GUID to your clipboard.

Add a header to the pkgdef file:

[$RootKey$\AD7Metrics\Engine\{your-guid-here}]

Every debugger needs a name, so let’s give ours one:

"Name"="Mock Debug Adapter"

Next, we need some boilerplate that will be the same for most debug adapters. You can look at the pkgdef file included in the SampleDebugAdapter project to learn more about what these settings do, but for now, we can just add:

; Boilerplate 
"CLSID"="{DAB324E9-7B35-454C-ACA8-F6BB0D5C8673}" 
"AlwaysLoadLocal"=dword:00000001 
"AddressBP"=dword:00000000 
"AutoSelectPriority"=dword:00000004 
"CallstackBP"=dword:00000000 

We need a few entries to describe the capabilities of our adapter. We don’t support Attach to Process, Exceptions, or Exception Conditions, so add:

; Capabilities 
"Attach"=dword:00000000 
"Exceptions"=dword:00000000 
"ExceptionConditions"=dword:00000000 

A few more entries tell VS what kind of language we’re debugging. The Mock Debug Adapter doesn’t have an associated language service, so we can just make up a name and give it an empty ID:

; Language Info 
"Language"="Mock Debugger" 
"LanguageId"="{00000000-0000-0000-0000-000000000000}" 

Finally, we need to tell VS how to launch our adapter. We need to specify the path to the adapter’s entry point ("adapter/out/mockDebug.js", in this case), and the runtime to use to launch it (Node.js v7.4.0). We can use the special pkgdef variable "$PackageFolder$", which will be replaced with the path to which our extension was installed when VS loads it:

; Launch Info 
"Adapter"="$PackageFolder$\adapter\out\mockDebug.js" 
"AdapterRuntime"="node-x86-7.4.0"

There are many other properties that can be specified to customize the behavior of the adapter in VS – see Special Properties Recognized by the Debug Adapter Host for a list.

Test the Mock Debug Adapter extension

With the adapter packaging complete, we can now test out our new extension in VS.

Build and install the extension

Hit F5 and VS will automatically build the extension, install it, and launch the "experimental" instance of VS.

Create a test folder

Create a folder somewhere on your system to hold a test project.

In the experimental instance of VS, open that folder by navigating to File -> Open -> Folder, then browse to and select the folder you created.

Create a test file

The mock debug adapter allows you to step through a text file line by line as if it was source code.

Right-click the folder node in Solution Explorer, then click Add -> New File. Name the file "MockDebug.txt"

Add some text to the file. Any text will work, and if a line contains the word “exception” the mock debug adapter will treat it as if it throws an exception. Here’s an example:

This 
is 
a 
test. 
 
This line will throw an exception!

Set a breakpoint on at least one line.

Create a launch configuration

Right-click the folder node in Solution Explorer, then click Add -> New File. Name the file "launch.json".

Paste the following content into the file:

{ 
    "type": "mock",
    "request": "launch",
    "program": "c:\\path\\to\\your\\folder\\MockDebug.txt"
}

The test launcher doesn’t support VS Code macros like ${workspaceFolder}, so you’ll need to specify a fully-qualified path for the **program **field.

NOTE: The mock debug adapter compares paths case-sensitively, so be sure the program path specified is cased exactly as it is on disk, and that the drive letter is in lower case. Otherwise, breakpoints will not work properly.

Enable adapter logging

The Debug Adapter Host can provide a great deal of debugging information through its logging mechanism, which can make debugging integration issues with debug adapters much simpler. In addition to a trace of all the CDP messages sent to or from the adapter, the log includes any warnings or errors generated by the Debug Adapter Host.

Open the Command Window by clicking View -> Other Windows -> Command Window.

In the command window, type:

DebugAdapterHost.Logging /On /OutputWindow

This will enable logging, and direct the log output to the Output window. If the Output window isn’t visible, you can open it by clicking View -> Output. The log output will appear in a separate Debug Adapter Host Log pane that you can view by selecting it in the Show output from dropdown. The pane won’t appear in the list unless there is log output to show.

Launch the adapter

We’re working on an improved launch experience that will integrate with the "Open Folder" experience so you can debug by hitting F5, but until that’s ready, you can use the "Launch Debug Adapter" tool that was installed when you built the VSDebugAdapterHostSamples solution.

Click Tools -> Launch Debug Adapter, then set Debug engine to the name you registered in your pkgdef, and Launch options to the "launch.json" file you created.

NOTE: If the Launch Debug Adapter menu item does not appear, be sure that you're using the "experimental" instance of VS, then try rebuilding the "VSDebugAdapterHostSamples" solution.

"Launch Debug Adapter" dialog, showing "Debug engine" and "Launch options" set as described in the text.

Click OK and the debug session will start. From here, you should be able to step, set breakpoints, and catch exceptions.

Visual Studio stopped at a breakpoint in "MockDebug.txt", demonstrating that the adapter extension works.

Debugging the adapter

If your debug adapter supports communication via a network socket instead of stdin and stdout, you can run it in a debugging environment of your preference and have the Debug Adapter Host connect to it by including the port number in the "$debugServer" property in your launch.json. For instance:

{
    // ... 
    "$debugServer": "4711" 
    // ... 
} 

If your adapter is Node-based, you can specify an adapter runtime with debugging enabled in your pkgdef, e.g.:

"AdapterRuntime"="node-x86-7.4.0-debug" 

This will start the Node runtime with additional arguments (--debug-brk=5858 --nolazy, in this case) which will cause it to wait for a debugger to connect at startup before executing the adapter code. Visual Studio can attach to such a process if the "Node.js development" workload is installed by clicking Debug -> Attach to Process..., then setting the Connection type to Node.js remote debugging and entering a connection target of tcp://localhost:5858/#ping=0.

Clone this wiki locally