Skip to content

Commit 6e78423

Browse files
authored
Merge pull request #210 from PowerShell/daviwil/pses-as-module
Consume Editor Services host as PowerShell module
2 parents 2e9b339 + e22921d commit 6e78423

File tree

9 files changed

+338
-162
lines changed

9 files changed

+338
-162
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ examples/Release/
33
examples/Tests/foo*.txt
44
out/
55
node_modules/
6+
logs/
7+
modules/*
8+
!modules/README.md
69
vscode-powershell.zip
710
vscps-preview.zip
811
*.vsix

.vscodeignore

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ build/**
77
bin/EditorServices.log
88
bin/DebugAdapter.log
99
bin/*.vshost.*
10+
logs/
11+

modules/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## `modules` folder README
2+
3+
This folder contains modules that are bundled with the vscode-powershell extension.
4+
All subfolders are not included in our GitHub repository, they are added here just
5+
before the module is published to the Visual Studio Marketplace.
6+
7+
This file serves as a placeholder so that the `modules` folder will be included
8+
in our Git repository.

package.json

+5-78
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,8 @@
118118
"powershell"
119119
]
120120
},
121-
"windows": {
122-
"program": "bin/Microsoft.PowerShell.EditorServices.Host.exe"
123-
},
124-
"winx86": {
125-
"program": "bin/Microsoft.PowerShell.EditorServices.Host.x86.exe"
126-
},
127-
"args": [
128-
"/debugAdapter",
129-
"/logLevel:Verbose",
130-
"/hostName:\"Visual Studio Code Host\"",
131-
"/hostProfileId:Microsoft.VSCode",
132-
"/hostVersion:0.6.1"
133-
],
121+
"program": "./out/debugAdapter.js",
122+
"runtime": "node",
134123
"configurationAttributes": {
135124
"launch": {
136125
"required": [
@@ -165,68 +154,6 @@
165154
"program": "${file}",
166155
"args": [],
167156
"cwd": "${file}"
168-
},
169-
{
170-
"name": "PowerShell x86",
171-
"type": "PowerShell x86",
172-
"request": "launch",
173-
"program": "${file}",
174-
"args": [],
175-
"cwd": "${file}"
176-
}
177-
]
178-
},
179-
{
180-
"type": "PowerShell x86",
181-
"enableBreakpointsFor": {
182-
"languageIds": [
183-
"powershell"
184-
]
185-
},
186-
"windows": {
187-
"program": "bin/Microsoft.PowerShell.EditorServices.Host.x86.exe"
188-
},
189-
"args": [
190-
"/debugAdapter",
191-
"/logLevel:Verbose",
192-
"/hostName:\"Visual Studio Code Host\"",
193-
"/hostProfileId:Microsoft.VSCode",
194-
"/hostVersion:0.6.1"
195-
],
196-
"configurationAttributes": {
197-
"launch": {
198-
"required": [
199-
"program"
200-
],
201-
"properties": {
202-
"program": {
203-
"type": "string",
204-
"description": "Absolute path to the PowerShell script to launch under the debugger."
205-
},
206-
"args": {
207-
"type": "array",
208-
"description": "Command line arguments to pass to the PowerShell script.",
209-
"items": {
210-
"type": "string"
211-
},
212-
"default": []
213-
},
214-
"cwd": {
215-
"type": "string",
216-
"description": "Absolute path to the working directory. Default is the current workspace.",
217-
"default": "."
218-
}
219-
}
220-
}
221-
},
222-
"initialConfigurations": [
223-
{
224-
"name": "PowerShell x86",
225-
"type": "PowerShell x86",
226-
"request": "launch",
227-
"program": "${file}",
228-
"args": [],
229-
"cwd": "${file}"
230157
}
231158
]
232159
}
@@ -255,10 +182,10 @@
255182
"default": "",
256183
"description": "Specifies the path to a PowerShell Script Analyzer settings file. Use either an absolute path (to override the default settings for all projects) or use a path relative to your workspace."
257184
},
258-
"powershell.developer.editorServicesHostPath": {
185+
"powershell.developer.bundledModulesPath": {
259186
"type": "string",
260-
"default": "../bin/",
261-
"description": "Specifies the path to the folder containing the PowerShell Editor Services host executables."
187+
"default": "../modules/",
188+
"description": "Specifies the path to the folder containing modules that are bundled with the PowerShell extension (i.e. PowerShell Editor Services, PowerShell Script Analyzer, Plaster)"
262189
},
263190
"powershell.developer.editorServicesLogLevel": {
264191
"type": "string",

scripts/Start-EditorServices.ps1

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
param(
2+
[Parameter(Mandatory=$true)]
3+
[ValidateNotNullOrEmpty()]
4+
[string]
5+
$EditorServicesVersion,
6+
7+
[Parameter(Mandatory=$true)]
8+
[ValidateNotNullOrEmpty()]
9+
[string]
10+
$HostName,
11+
12+
[Parameter(Mandatory=$true)]
13+
[ValidateNotNullOrEmpty()]
14+
[string]
15+
$HostProfileId,
16+
17+
[Parameter(Mandatory=$true)]
18+
[ValidateNotNullOrEmpty()]
19+
[string]
20+
$HostVersion,
21+
22+
[Parameter(Mandatory=$true)]
23+
[ValidateNotNullOrEmpty()]
24+
[string]
25+
$LanguageServicePipeName,
26+
27+
[Parameter(Mandatory=$true)]
28+
[ValidateNotNullOrEmpty()]
29+
[string]
30+
$DebugServicePipeName,
31+
32+
[ValidateNotNullOrEmpty()]
33+
[string]
34+
$BundledModulesPath,
35+
36+
[ValidateNotNullOrEmpty()]
37+
$LogPath,
38+
39+
[ValidateSet("Normal", "Verbose", "Error")]
40+
$LogLevel,
41+
42+
[switch]
43+
$WaitForCompletion,
44+
45+
[switch]
46+
$WaitForDebugger
47+
)
48+
49+
# Add BundledModulesPath to $env:PSModulePath
50+
if ($BundledModulesPath) {
51+
$env:PSModulePath = $BundledModulesPath + ";" + $env:PSModulePath
52+
}
53+
54+
$parsedVersion = [System.Version]::new($EditorServicesVersion)
55+
Import-Module PowerShellEditorServices -RequiredVersion $parsedVersion -ErrorAction Stop
56+
57+
Start-EditorServicesHost `
58+
-HostName $HostName `
59+
-HostProfileId $HostProfileId `
60+
-HostVersion $HostVersion `
61+
-LogPath $LogPath `
62+
-LogLevel $LogLevel `
63+
-LanguageServicePipeName $LanguageServicePipeName `
64+
-DebugServicePipeName $DebugServicePipeName `
65+
-BundledModulesPath $BundledModulesPath `
66+
-WaitForCompletion:$WaitForCompletion.IsPresent `
67+
-WaitForDebugger:$WaitForDebugger.IsPresent

src/debugAdapter.ts

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import fs = require('fs');
2+
import path = require('path');
3+
import net = require('net');
4+
import logging = require('./logging');
5+
6+
// NOTE: The purpose of this file is to serve as a bridge between
7+
// VS Code's debug adapter client (which communicates via stdio) and
8+
// PowerShell Editor Services' debug service (which communicates via
9+
// named pipes or a network protocol). It is purely a naive data
10+
// relay between the two transports.
11+
12+
var logBasePath = path.resolve(__dirname, "../logs");
13+
logging.ensurePathExists(logBasePath);
14+
15+
var debugAdapterLogWriter =
16+
fs.createWriteStream(
17+
path.resolve(
18+
logBasePath,
19+
logging.getLogName("DebugAdapterClient")));
20+
21+
// Pause the stdin buffer until we're connected to the
22+
// debug server
23+
process.stdin.pause();
24+
25+
// Establish connection before setting up the session
26+
let pipeName = "\\\\.\\pipe\\PSES-VSCode-DebugService-" + process.env.VSCODE_PID;
27+
debugAdapterLogWriter.write("Connecting to named pipe: " + pipeName + "\r\n");
28+
let debugServiceSocket = net.connect(pipeName);
29+
30+
// Write any errors to the log file
31+
debugServiceSocket.on(
32+
'error',
33+
(e) => debugAdapterLogWriter.write("Named pipe ERROR: " + e + "\r\n"));
34+
35+
// Route any output from the socket through stdout
36+
debugServiceSocket.on(
37+
'data',
38+
(data: Buffer) => process.stdout.write(data));
39+
40+
// Wait for the connection to complete
41+
debugServiceSocket.on(
42+
'connect',
43+
() => {
44+
debugAdapterLogWriter.write("Connected to named pipe: " + pipeName + "\r\n");
45+
46+
// When data comes on stdin, route it through the socket
47+
process.stdin.on(
48+
'data',
49+
(data: Buffer) => debugServiceSocket.write(data));
50+
51+
// Resume the stdin stream
52+
process.stdin.resume();
53+
});

src/logging.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import fs = require('fs');
2+
3+
export function ensurePathExists(targetPath: string) {
4+
// Ensure that the path exists
5+
try {
6+
fs.mkdirSync(targetPath);
7+
}
8+
catch (e) {
9+
// If the exception isn't to indicate that the folder
10+
// exists already, rethrow it.
11+
if (e.code != 'EEXIST') {
12+
throw e;
13+
}
14+
}
15+
}
16+
17+
export function getLogName(baseName: string): string {
18+
return Math.floor(Date.now() / 1000) + '-' + baseName + '.log';
19+
}

0 commit comments

Comments
 (0)