Skip to content

Commit 0fc0f3c

Browse files
authored
Merge pull request #242 from PowerShell/release/0.7.0
Release 0.7.0
2 parents ce858bb + 4c915c4 commit 0fc0f3c

File tree

9 files changed

+382
-127
lines changed

9 files changed

+382
-127
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# vscode-powershell Release History
22

3+
## 0.7.0
4+
### Thursday, August 18, 2016
5+
6+
#### Introducing support for Linux and macOS!
7+
8+
This release marks the beginning of our support for Linux and macOS via
9+
the new [cross-platform release of PowerShell](https://github.com/PowerShell/PowerShell).
10+
You can find installation and usage instructions at the [PowerShell GitHub repository](https://github.com/PowerShell/PowerShell).
11+
312
## 0.6.2
413
### Friday, August 12, 2016
514

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ how to use them.
2626

2727
This folder can be found at the following path:
2828
```
29-
$env:USERPROFILE\.vscode\extensions\ms-vscode.PowerShell-<version>\examples
29+
c:\Users\<yourusername>\.vscode\extensions\ms-vscode.PowerShell-<version>\examples
3030
```
3131
To open/view the extension's examples Visual Studio Code, run the following from your PowerShell command prompt:
3232
```

examples/StopTest.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
. .\Stop-Process2.ps1
1+
. ./Stop-Process2.ps1
22

33
notepad.exe
44
notepad.exe

package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "PowerShell",
33
"displayName": "PowerShell",
4-
"version": "0.6.2",
4+
"version": "0.7.0",
55
"publisher": "ms-vscode",
66
"description": "Develop PowerShell scripts in Visual Studio Code!",
77
"engines": {
@@ -182,6 +182,11 @@
182182
"default": "",
183183
"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."
184184
},
185+
"powershell.developer.powerShellExePath": {
186+
"type": "string",
187+
"default": "",
188+
"description": "Specifies the full path to a PowerShell executable. Used to change the installation of PowerShell used for language and debugging services."
189+
},
185190
"powershell.developer.bundledModulesPath": {
186191
"type": "string",
187192
"default": "../modules/",

scripts/Start-EditorServices.ps1

+145-24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
# PowerShell Editor Services Bootstrapper Script
2+
# ----------------------------------------------
3+
# This script contains startup logic for the PowerShell Editor Services
4+
# module when launched by an editor. It handles the following tasks:
5+
#
6+
# - Verifying the existence of dependencies like PowerShellGet
7+
# - Verifying that the expected version of the PowerShellEditorServices module is installed
8+
# - Installing the PowerShellEditorServices module if confirmed by the user
9+
# - Finding unused TCP port numbers for the language and debug services to use
10+
# - Starting the language and debug services from the PowerShellEditorServices module
11+
#
12+
# NOTE: If editor integration authors make modifications to this
13+
# script, please consider contributing changes back to the
14+
# canonical version of this script at the PowerShell Editor
15+
# Services GitHub repository:
16+
#
17+
# https://github.com/PowerShell/PowerShellEditorServices/blob/master/module/Start-EditorServices.ps1
18+
119
param(
220
[Parameter(Mandatory=$true)]
321
[ValidateNotNullOrEmpty()]
@@ -19,16 +37,6 @@ param(
1937
[string]
2038
$HostVersion,
2139

22-
[Parameter(Mandatory=$true)]
23-
[ValidateNotNullOrEmpty()]
24-
[string]
25-
$LanguageServicePipeName,
26-
27-
[Parameter(Mandatory=$true)]
28-
[ValidateNotNullOrEmpty()]
29-
[string]
30-
$DebugServicePipeName,
31-
3240
[ValidateNotNullOrEmpty()]
3341
[string]
3442
$BundledModulesPath,
@@ -40,28 +48,141 @@ param(
4048
$LogLevel,
4149

4250
[switch]
43-
$WaitForCompletion,
51+
$WaitForDebugger,
4452

4553
[switch]
46-
$WaitForDebugger
54+
$ConfirmInstall
4755
)
4856

57+
# This variable will be assigned later to contain information about
58+
# what happened while attempting to launch the PowerShell Editor
59+
# Services host
60+
$resultDetails = $null;
61+
62+
function Test-ModuleAvailable($ModuleName, $ModuleVersion) {
63+
$modules = Get-Module -ListAvailable $moduleName
64+
if ($modules -ne $null) {
65+
if ($ModuleVersion -ne $null) {
66+
foreach ($module in $modules) {
67+
if ($module.Version.Equals($moduleVersion)) {
68+
return $true;
69+
}
70+
}
71+
}
72+
else {
73+
return $true;
74+
}
75+
}
76+
77+
return $false;
78+
}
79+
80+
function Test-PortAvailability($PortNumber) {
81+
$portAvailable = $true;
82+
83+
try {
84+
$ipAddress = [System.Net.Dns]::GetHostEntryAsync("localhost").Result.AddressList[0];
85+
$tcpListener = [System.Net.Sockets.TcpListener]::new($ipAddress, $portNumber);
86+
$tcpListener.Start();
87+
$tcpListener.Stop();
88+
89+
}
90+
catch [System.Net.Sockets.SocketException] {
91+
# Check the SocketErrorCode to see if it's the expected exception
92+
if ($error[0].Exception.InnerException.SocketErrorCode -eq [System.Net.Sockets.SocketError]::AddressAlreadyInUse) {
93+
$portAvailable = $false;
94+
}
95+
else {
96+
Write-Output ("Error code: " + $error[0].SocketErrorCode)
97+
}
98+
}
99+
100+
return $portAvailable;
101+
}
102+
103+
$rand = [System.Random]::new()
104+
function Get-AvailablePort {
105+
$triesRemaining = 10;
106+
107+
while ($triesRemaining -gt 0) {
108+
$port = $rand.Next(10000, 30000)
109+
if ((Test-PortAvailability -PortAvailability $port) -eq $true) {
110+
return $port
111+
}
112+
113+
$triesRemaining--;
114+
}
115+
116+
return $null
117+
}
118+
49119
# Add BundledModulesPath to $env:PSModulePath
50120
if ($BundledModulesPath) {
51-
$env:PSModulePath = $BundledModulesPath + ";" + $env:PSModulePath
121+
$env:PSMODULEPATH = $BundledModulesPath + [System.IO.Path]::PathSeparator + $env:PSMODULEPATH
52122
}
53123

124+
# Check if PowerShellGet module is available
125+
if ((Test-ModuleAvailable "PowerShellGet") -eq $false) {
126+
# TODO: WRITE ERROR
127+
}
128+
129+
# Check if the expected version of the PowerShell Editor Services
130+
# module is installed
54131
$parsedVersion = [System.Version]::new($EditorServicesVersion)
132+
if ((Test-ModuleAvailable "PowerShellEditorServices" -RequiredVersion $parsedVersion) -eq $false) {
133+
if ($ConfirmInstall) {
134+
# TODO: Check for error and return failure if necessary
135+
Install-Module "PowerShellEditorServices" -RequiredVersion $parsedVersion -Confirm
136+
}
137+
else {
138+
# Indicate to the client that the PowerShellEditorServices module
139+
# needs to be installed
140+
Write-Output "needs_install"
141+
}
142+
}
143+
55144
Import-Module PowerShellEditorServices -RequiredVersion $parsedVersion -ErrorAction Stop
56145

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
146+
# Locate available port numbers for services
147+
$languageServicePort = Get-AvailablePort
148+
$debugServicePort = Get-AvailablePort
149+
150+
$editorServicesHost =
151+
Start-EditorServicesHost `
152+
-HostName $HostName `
153+
-HostProfileId $HostProfileId `
154+
-HostVersion $HostVersion `
155+
-LogPath $LogPath `
156+
-LogLevel $LogLevel `
157+
-LanguageServicePort $languageServicePort `
158+
-DebugServicePort $debugServicePort `
159+
-BundledModulesPath $BundledModulesPath `
160+
-WaitForDebugger:$WaitForDebugger.IsPresent
161+
162+
# TODO: Verify that the service is started
163+
164+
$resultDetails = @{
165+
"status" = "started";
166+
"channel" = "tcp";
167+
"languageServicePort" = $languageServicePort;
168+
"debugServicePort" = $debugServicePort;
169+
};
170+
171+
# Notify the client that the services have started
172+
Write-Output (ConvertTo-Json -InputObject $resultDetails -Compress)
173+
174+
try {
175+
# Wait for the host to complete execution before exiting
176+
$editorServicesHost.WaitForCompletion()
177+
}
178+
catch [System.Exception] {
179+
$e = $_.Exception; #.InnerException;
180+
$errorString = ""
181+
182+
while ($e -ne $null) {
183+
$errorString = $errorString + ($e.Message + "`r`n" + $e.StackTrace + "`r`n")
184+
$e = $e.InnerException;
185+
}
186+
187+
Write-Error ("`r`nCaught error while waiting for EditorServicesHost to complete:`r`n" + $errorString)
188+
}

src/debugAdapter.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fs = require('fs');
22
import path = require('path');
33
import net = require('net');
4+
import utils = require('./utils');
45
import logging = require('./logging');
56

67
// NOTE: The purpose of this file is to serve as a bridge between
@@ -10,7 +11,7 @@ import logging = require('./logging');
1011
// relay between the two transports.
1112

1213
var logBasePath = path.resolve(__dirname, "../logs");
13-
logging.ensurePathExists(logBasePath);
14+
utils.ensurePathExists(logBasePath);
1415

1516
var debugAdapterLogWriter =
1617
fs.createWriteStream(
@@ -22,15 +23,18 @@ var debugAdapterLogWriter =
2223
// debug server
2324
process.stdin.pause();
2425

26+
// Read the details of the current session to learn
27+
// the connection details for the debug service
28+
let sessionDetails = utils.readSessionFile();
29+
2530
// 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);
31+
debugAdapterLogWriter.write("Connecting to port: " + sessionDetails.debugServicePort + "\r\n");
32+
let debugServiceSocket = net.connect(sessionDetails.debugServicePort);
2933

3034
// Write any errors to the log file
3135
debugServiceSocket.on(
3236
'error',
33-
(e) => debugAdapterLogWriter.write("Named pipe ERROR: " + e + "\r\n"));
37+
(e) => debugAdapterLogWriter.write("Socket connect ERROR: " + e + "\r\n"));
3438

3539
// Route any output from the socket through stdout
3640
debugServiceSocket.on(
@@ -41,7 +45,7 @@ debugServiceSocket.on(
4145
debugServiceSocket.on(
4246
'connect',
4347
() => {
44-
debugAdapterLogWriter.write("Connected to named pipe: " + pipeName + "\r\n");
48+
debugAdapterLogWriter.write("Connected to socket!\r\n\r\n");
4549

4650
// When data comes on stdin, route it through the socket
4751
process.stdin.on(
@@ -51,3 +55,17 @@ debugServiceSocket.on(
5155
// Resume the stdin stream
5256
process.stdin.resume();
5357
});
58+
59+
// When the socket closes, end the session
60+
debugServiceSocket.on(
61+
'close',
62+
() => {
63+
debugAdapterLogWriter.write("Socket closed, shutting down.");
64+
65+
// Close after a short delay to give the client time
66+
// to finish up
67+
setTimeout(() => {
68+
process.exit(0);
69+
}, 1000);
70+
}
71+
)

src/logging.ts

-14
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
import fs = require('fs');
22

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-
173
export function getLogName(baseName: string): string {
184
return Math.floor(Date.now() / 1000) + '-' + baseName + '.log';
195
}

0 commit comments

Comments
 (0)