Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable debugging in temporary Integrated Console sessions #883

Merged
merged 2 commits into from
Jun 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
"args": [],
"cwd": "${file}"
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch Current File in Temporary Console",
"script": "${file}",
"args": [],
"cwd": "${file}",
"createTemporaryIntegratedConsole": true
},
{
"type": "PowerShell",
"request": "launch",
Expand Down
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,19 @@
"cwd": "^\"\\${file}\""
}
},
{
"label": "PowerShell: Launch Current File in Temporary Console",
"description": "Launch current file (in active editor window) under debugger in a temporary Integrated Console.",
"body": {
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch Current File in Temporary Console",
"script": "^\"\\${file}\"",
"args": [],
"cwd": "^\"\\${file}\"",
"createTemporaryIntegratedConsole": true
}
},
{
"label": "PowerShell: Launch - Current File w/Args Prompt",
"description": "Launch current file (in active editor window) under debugger, prompting first for script arguments",
Expand Down Expand Up @@ -292,6 +305,11 @@
"type": "string",
"description": "Absolute path to the working directory. Default is the current workspace.",
"default": "${workspaceRoot}"
},
"createTemporaryIntegratedConsole": {
"type": "boolean",
"description": "Determines whether a temporary PowerShell Integrated Console is created for each debugging session, useful for debugging PowerShell classes and binary modules. Overrides the user setting 'powershell.debugging.createTemporaryIntegratedConsole'.",
"default": false
}
}
},
Expand Down Expand Up @@ -323,6 +341,15 @@
"args": [],
"cwd": "${file}"
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch Current File in Temporary Console",
"script": "${file}",
"args": [],
"cwd": "${file}",
"createTemporaryIntegratedConsole": true
},
{
"type": "PowerShell",
"request": "launch",
Expand Down Expand Up @@ -448,6 +475,11 @@
"default": true,
"description": "Switches focus to the console when a script selection is run or a script file is debugged. This is an accessibility feature. To disable it, set to false."
},
"powershell.debugging.createTemporaryIntegratedConsole": {
"type": "boolean",
"default": false,
"description": "Determines whether a temporary PowerShell Integrated Console is created for each debugging session, useful for debugging PowerShell classes and binary modules."
},
"powershell.developer.bundledModulesPath": {
"type": "string",
"description": "Specifies an alternate path to the folder containing modules that are bundled with the PowerShell extension (i.e. PowerShell Editor Services, PSScriptAnalyzer, Plaster)"
Expand Down
2 changes: 1 addition & 1 deletion scripts/Start-EditorServices.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ param(
[switch]
$EnableConsoleRepl,

[string]
[switch]
$DebugServiceOnly,

[string[]]
Expand Down
46 changes: 41 additions & 5 deletions src/features/DebugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import vscode = require('vscode');
import utils = require('../utils');
import Settings = require('../settings');
import { IFeature } from '../feature';
import { SessionManager } from '../session';
import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient';
Expand All @@ -13,6 +14,8 @@ export namespace StartDebuggerNotification {
}

export class DebugSessionFeature implements IFeature {

private sessionCount: number = 1;
private command: vscode.Disposable;
private examplesPath: string;

Expand Down Expand Up @@ -42,6 +45,9 @@ export class DebugSessionFeature implements IFeature {
let debugCurrentScript = (config.script === "${file}") || !config.request;
let generateLaunchConfig = !config.request;

var settings = Settings.load();
let createNewIntegratedConsole = settings.debugging.createTemporaryIntegratedConsole;

if (generateLaunchConfig) {
// No launch.json, create the default configuration for both unsaved (Untitled) and saved documents.
config.type = 'PowerShell';
Expand Down Expand Up @@ -106,20 +112,50 @@ export class DebugSessionFeature implements IFeature {
}
}
}

if (config.createTemporaryIntegratedConsole !== undefined) {
createNewIntegratedConsole = config.createTemporaryIntegratedConsole;
}
}

// Prevent the Debug Console from opening
config.internalConsoleOptions = "neverOpen";

// Create or show the interactive console
// TODO #367: Check if "newSession" mode is configured
vscode.commands.executeCommand('PowerShell.ShowSessionConsole', true);

// Write out temporary debug session file
utils.writeSessionFile(
utils.getDebugSessionFilePath(),
this.sessionManager.getSessionDetails());
var sessionFilePath = utils.getDebugSessionFilePath();

if (createNewIntegratedConsole) {
var debugProcess =
this.sessionManager.createDebugSessionProcess(
sessionFilePath,
settings);

debugProcess
.start(`DebugSession-${this.sessionCount++}`)
.then(
sessionDetails => {
this.startDebugger(
config,
sessionFilePath,
sessionDetails);
});
}
else {
this.startDebugger(
config,
sessionFilePath,
this.sessionManager.getSessionDetails());
}
}

private startDebugger(
config: any,
sessionFilePath: string,
sessionDetails: utils.EditorServicesSessionDetails) {

utils.writeSessionFile(sessionFilePath, sessionDetails);
vscode.commands.executeCommand('vscode.startDebug', config);
}
}
Expand Down
181 changes: 181 additions & 0 deletions src/process.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*---------------------------------------------------------
* 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 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 title: string,
private log: Logger,
private startArgs: string,
private sessionFilePath: string,
private sessionSettings: Settings.ISettings) {
}

public start(logFileName: 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(logFileName);

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

this.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 + "' " + this.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(
this.title,
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 + ' ' + this.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