Skip to content

Commit a60aae0

Browse files
committed
Factor SessionManager's process launching out to PowerShellProcess
This change moves SessionManager's process launching behavior into a new class called PowerShellProcess which will be used for launching additional PowerShell processes to enable fresh, transient debugging sessions.
1 parent 8cffa08 commit a60aae0

File tree

3 files changed

+235
-151
lines changed

3 files changed

+235
-151
lines changed

src/process.ts

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*---------------------------------------------------------
2+
* Copyright (C) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------*/
4+
5+
import os = require('os');
6+
import fs = require('fs');
7+
import net = require('net');
8+
import path = require('path');
9+
import utils = require('./utils');
10+
import vscode = require('vscode');
11+
import cp = require('child_process');
12+
import Settings = require('./settings');
13+
14+
import { Logger } from './logging';
15+
16+
export class PowerShellProcess {
17+
18+
private sessionFilePath: string;
19+
private consoleTerminal: vscode.Terminal = undefined;
20+
private consoleCloseSubscription: vscode.Disposable;
21+
private sessionDetails: utils.EditorServicesSessionDetails;
22+
23+
private onExitedEmitter = new vscode.EventEmitter<void>();
24+
public onExited: vscode.Event<void> = this.onExitedEmitter.event;
25+
26+
constructor(
27+
public exePath: string,
28+
private log: Logger,
29+
private sessionSettings: Settings.ISettings) {
30+
31+
this.sessionFilePath =
32+
utils.getSessionFilePath(
33+
Math.floor(100000 + Math.random() * 900000));
34+
}
35+
36+
public start(startArgs: string): Thenable<utils.EditorServicesSessionDetails> {
37+
38+
return new Promise<utils.EditorServicesSessionDetails>(
39+
(resolve, reject) => {
40+
try
41+
{
42+
let startScriptPath =
43+
path.resolve(
44+
__dirname,
45+
'../scripts/Start-EditorServices.ps1');
46+
47+
var editorServicesLogPath = this.log.getLogFilePath("EditorServices");
48+
49+
var featureFlags =
50+
this.sessionSettings.developer.featureFlags !== undefined
51+
? this.sessionSettings.developer.featureFlags.map(f => `'${f}'`).join(', ')
52+
: "";
53+
54+
startArgs +=
55+
`-LogPath '${editorServicesLogPath}' ` +
56+
`-SessionDetailsPath '${this.sessionFilePath}' ` +
57+
`-FeatureFlags @(${featureFlags})`
58+
59+
var powerShellArgs = [
60+
"-NoProfile",
61+
"-NonInteractive"
62+
]
63+
64+
// Only add ExecutionPolicy param on Windows
65+
if (utils.isWindowsOS()) {
66+
powerShellArgs.push("-ExecutionPolicy", "Unrestricted")
67+
}
68+
69+
powerShellArgs.push(
70+
"-Command",
71+
"& '" + startScriptPath + "' " + startArgs);
72+
73+
var powerShellExePath = this.exePath;
74+
75+
if (this.sessionSettings.developer.powerShellExeIsWindowsDevBuild) {
76+
// Windows PowerShell development builds need the DEVPATH environment
77+
// variable set to the folder where development binaries are held
78+
79+
// NOTE: This batch file approach is needed temporarily until VS Code's
80+
// createTerminal API gets an argument for setting environment variables
81+
// on the launched process.
82+
var batScriptPath = path.resolve(__dirname, '../sessions/powershell.bat');
83+
fs.writeFileSync(
84+
batScriptPath,
85+
`@set DEVPATH=${path.dirname(powerShellExePath)}\r\n@${powerShellExePath} %*`);
86+
87+
powerShellExePath = batScriptPath;
88+
}
89+
90+
this.log.write(`${utils.getTimestampString()} Language server starting...`);
91+
92+
// Make sure no old session file exists
93+
utils.deleteSessionFile(this.sessionFilePath);
94+
95+
// Launch PowerShell in the integrated terminal
96+
this.consoleTerminal =
97+
vscode.window.createTerminal(
98+
"PowerShell Integrated Console",
99+
powerShellExePath,
100+
powerShellArgs);
101+
102+
if (this.sessionSettings.integratedConsole.showOnStartup) {
103+
this.consoleTerminal.show(true);
104+
}
105+
106+
// Start the language client
107+
utils.waitForSessionFile(
108+
this.sessionFilePath,
109+
(sessionDetails, error) => {
110+
// Clean up the session file
111+
utils.deleteSessionFile(this.sessionFilePath);
112+
113+
if (error) {
114+
reject(error);
115+
}
116+
else {
117+
this.sessionDetails = sessionDetails;
118+
resolve(this.sessionDetails);
119+
}
120+
});
121+
122+
// this.powerShellProcess.stderr.on(
123+
// 'data',
124+
// (data) => {
125+
// this.log.writeError("ERROR: " + data);
126+
127+
// if (this.sessionStatus === SessionStatus.Initializing) {
128+
// this.setSessionFailure("PowerShell could not be started, click 'Show Logs' for more details.");
129+
// }
130+
// else if (this.sessionStatus === SessionStatus.Running) {
131+
// this.promptForRestart();
132+
// }
133+
// });
134+
135+
this.consoleCloseSubscription =
136+
vscode.window.onDidCloseTerminal(
137+
terminal => {
138+
if (terminal === this.consoleTerminal) {
139+
this.log.write(os.EOL + "powershell.exe terminated or terminal UI was closed" + os.EOL);
140+
this.onExitedEmitter.fire();
141+
}
142+
});
143+
144+
this.consoleTerminal.processId.then(
145+
pid => {
146+
console.log("powershell.exe started, pid: " + pid + ", exe: " + powerShellExePath);
147+
this.log.write(
148+
"powershell.exe started --",
149+
" pid: " + pid,
150+
" exe: " + powerShellExePath,
151+
" args: " + startScriptPath + ' ' + startArgs + os.EOL + os.EOL);
152+
});
153+
}
154+
catch (e)
155+
{
156+
reject(e);
157+
}
158+
});
159+
}
160+
161+
public showConsole(preserveFocus: boolean) {
162+
if (this.consoleTerminal) {
163+
this.consoleTerminal.show(preserveFocus);
164+
}
165+
}
166+
167+
public dispose() {
168+
169+
// Clean up the session file
170+
utils.deleteSessionFile(this.sessionFilePath);
171+
172+
if (this.consoleCloseSubscription) {
173+
this.consoleCloseSubscription.dispose();
174+
this.consoleCloseSubscription = undefined;
175+
}
176+
177+
if (this.consoleTerminal) {
178+
this.log.write(os.EOL + "Terminating PowerShell process...");
179+
this.consoleTerminal.dispose();
180+
this.consoleTerminal = undefined;
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)