Skip to content

Commit 7849b0b

Browse files
authored
Merge pull request #423 from PowerShell/daviwil/debug-attach
Add new "attach" and "interactive" debugging configurations
2 parents b9bb746 + d95a375 commit 7849b0b

File tree

4 files changed

+131
-6
lines changed

4 files changed

+131
-6
lines changed

examples/PSScriptAnalyzerSettings.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
'PSReservedParams',
1717
'PSShouldProcess',
1818
'PSUseApprovedVerbs',
19+
'PSAvoidUsingAliases',
1920
'PSUseDeclaredVarsMoreThanAssigments')
2021

2122
# Do not analyze the following rules. Use ExcludeRules when you have

package.json

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160

161161
"configurationSnippets": [
162162
{
163-
"label": "PowerShell: Launch Current File Configuration",
163+
"label": "PowerShell: Launch Current Script Configuration",
164164
"description": "A new configuration for launching the current opened PowerShell script",
165165
"body": {
166166
"type": "PowerShell",
@@ -172,7 +172,7 @@
172172
}
173173
},
174174
{
175-
"label": "PowerShell: Launch Configuration",
175+
"label": "PowerShell: Launch Script Configuration",
176176
"description": "A new configuration for launching a PowerShell script",
177177
"body": {
178178
"type": "PowerShell",
@@ -182,22 +182,39 @@
182182
"args": [],
183183
"cwd": "^\"\\${workspaceRoot}\""
184184
}
185+
},
186+
{
187+
"label": "PowerShell: Attach to PowerShell Process Configuration",
188+
"description": "A new configuration for debugging a runspace in another process.",
189+
"body": {
190+
"type": "PowerShell",
191+
"request": "attach",
192+
"name": "PowerShell Attach to Process",
193+
"processId": "${ProcessId}",
194+
"runspaceId": "1"
195+
}
196+
},
197+
{
198+
"label": "PowerShell: Launch Interactive Session Configuration",
199+
"description": "A new configuration for debugging an interactive session.",
200+
"body": {
201+
"type": "PowerShell",
202+
"request": "launch",
203+
"name": "PowerShell Interactive Session"
204+
}
185205
}
186206
],
187207

188208
"configurationAttributes": {
189209
"launch": {
190-
"required": [
191-
"script"
192-
],
193210
"properties": {
194211
"program": {
195212
"type": "string",
196213
"description": "Deprecated. Please use the 'script' property instead to specify the absolute path to the PowerShell script to launch under the debugger."
197214
},
198215
"script": {
199216
"type": "string",
200-
"description": "Absolute path to the PowerShell script to launch under the debugger."
217+
"description": "Optional: Absolute path to the PowerShell script to launch under the debugger."
201218
},
202219
"args": {
203220
"type": "array",
@@ -213,6 +230,23 @@
213230
"default": "${workspaceRoot}"
214231
}
215232
}
233+
},
234+
"attach": {
235+
"properties": {
236+
"computerName": {
237+
"type": "string",
238+
"description": "Optional: The computer name to which a remote session will be established. Works only on PowerShell 4 and above."
239+
},
240+
"processId": {
241+
"type": "number",
242+
"description": "The ID of the process to be attached. Works only on PowerShell 5 and above."
243+
},
244+
"runspaceId": {
245+
"type": "number",
246+
"description": "Optional: The ID of the runspace to debug in the attached process. Defaults to 1. Works only on PowerShell 5 and above.",
247+
"default": 1
248+
}
249+
}
216250
}
217251
},
218252
"initialConfigurations": [
@@ -223,6 +257,18 @@
223257
"script": "${file}",
224258
"args": [],
225259
"cwd": "${file}"
260+
},
261+
{
262+
"type": "PowerShell",
263+
"request": "attach",
264+
"name": "PowerShell Attach",
265+
"processId": "12345"
266+
},
267+
{
268+
"type": "PowerShell",
269+
"request": "launch",
270+
"name": "PowerShell Interactive Session",
271+
"cwd": "${workspaceRoot}"
226272
}
227273
]
228274
}

src/features/ExtensionCommands.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ export namespace OpenFileRequest {
122122
{ get method() { return 'editor/openFile'; } };
123123
}
124124

125+
export namespace CloseFileRequest {
126+
export const type: RequestType<string, EditorOperationResponse, void> =
127+
{ get method() { return 'editor/closeFile'; } };
128+
}
129+
125130
export namespace ShowErrorMessageRequest {
126131
export const type: RequestType<string, EditorOperationResponse, void> =
127132
{ get method() { return 'editor/showErrorMessage'; } };
@@ -198,6 +203,10 @@ export class ExtensionCommandsFeature implements IFeature {
198203
OpenFileRequest.type,
199204
filePath => this.openFile(filePath));
200205

206+
this.languageClient.onRequest(
207+
CloseFileRequest.type,
208+
filePath => this.closeFile(filePath));
209+
201210
this.languageClient.onRequest(
202211
ShowInformationMessageRequest.type,
203212
message => this.showInformationMessage(message));
@@ -317,6 +326,37 @@ export class ExtensionCommandsFeature implements IFeature {
317326
return promise;
318327
}
319328

329+
private closeFile(filePath: string): Thenable<EditorOperationResponse> {
330+
331+
var promise: Thenable<EditorOperationResponse>;
332+
333+
// Make sure the file path is absolute
334+
if (!path.win32.isAbsolute(filePath))
335+
{
336+
filePath = path.win32.resolve(
337+
vscode.workspace.rootPath,
338+
filePath);
339+
}
340+
341+
// Normalize file path case for comparison
342+
var normalizedFilePath = filePath.toLowerCase();
343+
344+
if (vscode.workspace.textDocuments.find(doc => doc.fileName.toLowerCase() == normalizedFilePath))
345+
{
346+
promise =
347+
vscode.workspace.openTextDocument(filePath)
348+
.then(doc => vscode.window.showTextDocument(doc))
349+
.then(editor => vscode.commands.executeCommand("workbench.action.closeActiveEditor"))
350+
.then(_ => EditorOperationResponse.Completed);
351+
}
352+
else
353+
{
354+
promise = Promise.resolve(EditorOperationResponse.Completed);
355+
}
356+
357+
return promise;
358+
}
359+
320360
private setSelection(details: SetSelectionRequestArguments): EditorOperationResponse {
321361
vscode.window.activeTextEditor.selections = [
322362
new vscode.Selection(

src/session.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,23 @@ export class SessionManager {
189189
}
190190
}
191191

192+
private setStatusBarVersionString(
193+
runspaceDetails: RunspaceDetails) {
194+
195+
var versionString =
196+
this.versionDetails.architecture === "x86"
197+
? `${runspaceDetails.powerShellVersion.displayVersion} (${runspaceDetails.powerShellVersion.architecture})`
198+
: runspaceDetails.powerShellVersion.displayVersion;
199+
200+
if (runspaceDetails.runspaceType != RunspaceType.Local) {
201+
versionString += ` [${runspaceDetails.connectionString}]`
202+
}
203+
204+
this.setSessionStatus(
205+
versionString,
206+
SessionStatus.Running);
207+
}
208+
192209
private registerCommands() : void {
193210
this.registeredCommands = [
194211
vscode.commands.registerCommand('PowerShell.RestartSession', () => { this.restartSession(); }),
@@ -365,6 +382,10 @@ export class SessionManager {
365382
this.setSessionFailure("Could not start language service: ", reason);
366383
});
367384

385+
this.languageServerClient.onNotification(
386+
RunspaceChangedEvent.type,
387+
(runspaceDetails) => { this.setStatusBarVersionString(runspaceDetails); });
388+
368389
this.languageServerClient.start();
369390
}
370391
catch (e)
@@ -623,3 +644,20 @@ export interface PowerShellVersionDetails {
623644
edition: string;
624645
architecture: string;
625646
}
647+
648+
export enum RunspaceType {
649+
Local,
650+
Process,
651+
Remote
652+
}
653+
654+
export interface RunspaceDetails {
655+
powerShellVersion: PowerShellVersionDetails;
656+
runspaceType: RunspaceType;
657+
connectionString: string;
658+
}
659+
660+
export namespace RunspaceChangedEvent {
661+
export const type: NotificationType<RunspaceDetails> =
662+
{ get method() { return 'powerShell/runspaceChanged'; } };
663+
}

0 commit comments

Comments
 (0)