@@ -80,6 +80,20 @@ export class DebugSessionFeature implements IFeature, DebugConfigurationProvider
80
80
// if nothing is set, prompt for the processId
81
81
if ( ! config . customPipeName && ! config . processId ) {
82
82
config . processId = await vscode . commands . executeCommand ( "PowerShell.PickPSHostProcess" ) ;
83
+
84
+ // No process selected. Cancel attach.
85
+ if ( ! config . processId ) {
86
+ return null ;
87
+ }
88
+ }
89
+
90
+ if ( ! config . runspaceId ) {
91
+ config . runspaceId = await vscode . commands . executeCommand ( "PowerShell.PickRunspace" , config . processId ) ;
92
+
93
+ // No runspace selected. Cancel attach.
94
+ if ( ! config . runspaceId ) {
95
+ return null ;
96
+ }
83
97
}
84
98
}
85
99
@@ -386,3 +400,122 @@ export class PickPSHostProcessFeature implements IFeature {
386
400
}
387
401
}
388
402
}
403
+
404
+ interface IRunspaceItem extends vscode . QuickPickItem {
405
+ id : string ; // payload for the QuickPick UI
406
+ }
407
+
408
+ interface IRunspace {
409
+ id : number ;
410
+ name : string ;
411
+ availability : string ;
412
+ }
413
+
414
+ export const GetRunspaceRequestType =
415
+ new RequestType < any , IRunspace [ ] , string , void > ( "powerShell/getRunspace" ) ;
416
+
417
+ export class PickRunspaceFeature implements IFeature {
418
+
419
+ private command : vscode . Disposable ;
420
+ private languageClient : LanguageClient ;
421
+ private waitingForClientToken : vscode . CancellationTokenSource ;
422
+ private getLanguageClientResolve : ( value ?: LanguageClient | Thenable < LanguageClient > ) => void ;
423
+
424
+ constructor ( ) {
425
+ this . command =
426
+ vscode . commands . registerCommand ( "PowerShell.PickRunspace" , ( processId ) => {
427
+ return this . getLanguageClient ( )
428
+ . then ( ( _ ) => this . pickRunspace ( processId ) , ( _ ) => undefined ) ;
429
+ } , this ) ;
430
+ }
431
+
432
+ public setLanguageClient ( languageClient : LanguageClient ) {
433
+ this . languageClient = languageClient ;
434
+
435
+ if ( this . waitingForClientToken ) {
436
+ this . getLanguageClientResolve ( this . languageClient ) ;
437
+ this . clearWaitingToken ( ) ;
438
+ }
439
+ }
440
+
441
+ public dispose ( ) {
442
+ this . command . dispose ( ) ;
443
+ }
444
+
445
+ private getLanguageClient ( ) : Thenable < LanguageClient > {
446
+ if ( this . languageClient ) {
447
+ return Promise . resolve ( this . languageClient ) ;
448
+ } else {
449
+ // If PowerShell isn't finished loading yet, show a loading message
450
+ // until the LanguageClient is passed on to us
451
+ this . waitingForClientToken = new vscode . CancellationTokenSource ( ) ;
452
+
453
+ return new Promise < LanguageClient > (
454
+ ( resolve , reject ) => {
455
+ this . getLanguageClientResolve = resolve ;
456
+
457
+ vscode . window
458
+ . showQuickPick (
459
+ [ "Cancel" ] ,
460
+ { placeHolder : "Attach to PowerShell host process: Please wait, starting PowerShell..." } ,
461
+ this . waitingForClientToken . token )
462
+ . then ( ( response ) => {
463
+ if ( response === "Cancel" ) {
464
+ this . clearWaitingToken ( ) ;
465
+ reject ( ) ;
466
+ }
467
+ } ) ;
468
+
469
+ // Cancel the loading prompt after 60 seconds
470
+ setTimeout ( ( ) => {
471
+ if ( this . waitingForClientToken ) {
472
+ this . clearWaitingToken ( ) ;
473
+ reject ( ) ;
474
+
475
+ vscode . window . showErrorMessage (
476
+ "Attach to PowerShell host process: PowerShell session took too long to start." ) ;
477
+ }
478
+ } , 60000 ) ;
479
+ } ,
480
+ ) ;
481
+ }
482
+ }
483
+
484
+ private pickRunspace ( processId ) : Thenable < string > {
485
+ return this . languageClient . sendRequest ( GetRunspaceRequestType , processId ) . then ( ( response ) => {
486
+ const items : IRunspaceItem [ ] = [ ] ;
487
+
488
+ for ( const runspace of response ) {
489
+ // Skip default runspace
490
+ if ( runspace . id === 1 || runspace . name === "PSAttachRunspace" ) {
491
+ continue ;
492
+ }
493
+
494
+ items . push ( {
495
+ label : runspace . name ,
496
+ description : `ID: ${ runspace . id } - ${ runspace . availability } ` ,
497
+ id : runspace . id . toString ( ) ,
498
+ } ) ;
499
+ }
500
+
501
+ const options : vscode . QuickPickOptions = {
502
+ placeHolder : "Select PowerShell runspace to debug" ,
503
+ matchOnDescription : true ,
504
+ matchOnDetail : true ,
505
+ } ;
506
+
507
+ return vscode . window . showQuickPick ( items , options ) . then ( ( item ) => {
508
+ // Return undefined when user presses Esc.
509
+ // This prevents VSCode from opening launch.json in this case which happens if we return "".
510
+ return item ? `${ item . id } ` : undefined ;
511
+ } ) ;
512
+ } ) ;
513
+ }
514
+
515
+ private clearWaitingToken ( ) {
516
+ if ( this . waitingForClientToken ) {
517
+ this . waitingForClientToken . dispose ( ) ;
518
+ this . waitingForClientToken = undefined ;
519
+ }
520
+ }
521
+ }
0 commit comments