Skip to content

Commit

Permalink
Factor SessionManager's process launching out to PowerShellProcess
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
daviwil committed Jun 21, 2017
1 parent 8cffa08 commit a60aae0
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 151 deletions.
183 changes: 183 additions & 0 deletions src/process.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import os = require('os');
import fs = require('fs');
import net = require('net');
import path = require('path');
import utils = require('./utils');
import vscode = require('vscode');
import cp = require('child_process');
import Settings = require('./settings');

import { Logger } from './logging';

export class PowerShellProcess {

private sessionFilePath: string;
private consoleTerminal: vscode.Terminal = undefined;
private consoleCloseSubscription: vscode.Disposable;
private sessionDetails: utils.EditorServicesSessionDetails;

private onExitedEmitter = new vscode.EventEmitter<void>();
public onExited: vscode.Event<void> = this.onExitedEmitter.event;

constructor(
public exePath: string,
private log: Logger,
private sessionSettings: Settings.ISettings) {

this.sessionFilePath =
utils.getSessionFilePath(
Math.floor(100000 + Math.random() * 900000));
}

public start(startArgs: string): Thenable<utils.EditorServicesSessionDetails> {

return new Promise<utils.EditorServicesSessionDetails>(
(resolve, reject) => {
try
{
let startScriptPath =
path.resolve(
__dirname,
'../scripts/Start-EditorServices.ps1');

var editorServicesLogPath = this.log.getLogFilePath("EditorServices");

var featureFlags =
this.sessionSettings.developer.featureFlags !== undefined
? this.sessionSettings.developer.featureFlags.map(f => `'${f}'`).join(', ')
: "";

startArgs +=
`-LogPath '${editorServicesLogPath}' ` +
`-SessionDetailsPath '${this.sessionFilePath}' ` +
`-FeatureFlags @(${featureFlags})`

var powerShellArgs = [
"-NoProfile",
"-NonInteractive"
]

// Only add ExecutionPolicy param on Windows
if (utils.isWindowsOS()) {
powerShellArgs.push("-ExecutionPolicy", "Unrestricted")
}

powerShellArgs.push(
"-Command",
"& '" + startScriptPath + "' " + startArgs);

var powerShellExePath = this.exePath;

if (this.sessionSettings.developer.powerShellExeIsWindowsDevBuild) {
// Windows PowerShell development builds need the DEVPATH environment
// variable set to the folder where development binaries are held

// NOTE: This batch file approach is needed temporarily until VS Code's
// createTerminal API gets an argument for setting environment variables
// on the launched process.
var batScriptPath = path.resolve(__dirname, '../sessions/powershell.bat');
fs.writeFileSync(
batScriptPath,
`@set DEVPATH=${path.dirname(powerShellExePath)}\r\n@${powerShellExePath} %*`);

powerShellExePath = batScriptPath;
}

this.log.write(`${utils.getTimestampString()} Language server starting...`);

// Make sure no old session file exists
utils.deleteSessionFile(this.sessionFilePath);

// Launch PowerShell in the integrated terminal
this.consoleTerminal =
vscode.window.createTerminal(
"PowerShell Integrated Console",
powerShellExePath,
powerShellArgs);

if (this.sessionSettings.integratedConsole.showOnStartup) {
this.consoleTerminal.show(true);
}

// Start the language client
utils.waitForSessionFile(
this.sessionFilePath,
(sessionDetails, error) => {
// Clean up the session file
utils.deleteSessionFile(this.sessionFilePath);

if (error) {
reject(error);
}
else {
this.sessionDetails = sessionDetails;
resolve(this.sessionDetails);
}
});

// this.powerShellProcess.stderr.on(
// 'data',
// (data) => {
// this.log.writeError("ERROR: " + data);

// if (this.sessionStatus === SessionStatus.Initializing) {
// this.setSessionFailure("PowerShell could not be started, click 'Show Logs' for more details.");
// }
// else if (this.sessionStatus === SessionStatus.Running) {
// this.promptForRestart();
// }
// });

this.consoleCloseSubscription =
vscode.window.onDidCloseTerminal(
terminal => {
if (terminal === this.consoleTerminal) {
this.log.write(os.EOL + "powershell.exe terminated or terminal UI was closed" + os.EOL);
this.onExitedEmitter.fire();
}
});

this.consoleTerminal.processId.then(
pid => {
console.log("powershell.exe started, pid: " + pid + ", exe: " + powerShellExePath);
this.log.write(
"powershell.exe started --",
" pid: " + pid,
" exe: " + powerShellExePath,
" args: " + startScriptPath + ' ' + startArgs + os.EOL + os.EOL);
});
}
catch (e)
{
reject(e);
}
});
}

public showConsole(preserveFocus: boolean) {
if (this.consoleTerminal) {
this.consoleTerminal.show(preserveFocus);
}
}

public dispose() {

// Clean up the session file
utils.deleteSessionFile(this.sessionFilePath);

if (this.consoleCloseSubscription) {
this.consoleCloseSubscription.dispose();
this.consoleCloseSubscription = undefined;
}

if (this.consoleTerminal) {
this.log.write(os.EOL + "Terminating PowerShell process...");
this.consoleTerminal.dispose();
this.consoleTerminal = undefined;
}
}
}
Loading

0 comments on commit a60aae0

Please sign in to comment.