@@ -23,6 +23,8 @@ namespace Microsoft.PowerShell.EditorServices.Protocol.Server
23
23
{
24
24
public class DebugAdapter
25
25
{
26
+ private static readonly Version _minVersionForCustomPipeName = new Version ( 6 , 2 ) ;
27
+
26
28
private EditorSession _editorSession ;
27
29
28
30
private bool _noDebug ;
@@ -350,11 +352,17 @@ protected async Task HandleAttachRequestAsync(
350
352
351
353
RegisterEventHandlers ( ) ;
352
354
355
+ bool processIdIsSet = ! string . IsNullOrEmpty ( attachParams . ProcessId ) && attachParams . ProcessId != "undefined" ;
356
+ bool customPipeNameIsSet = ! string . IsNullOrEmpty ( attachParams . CustomPipeName ) && attachParams . CustomPipeName != "undefined" ;
357
+
358
+ PowerShellVersionDetails runspaceVersion =
359
+ _editorSession . PowerShellContext . CurrentRunspace . PowerShellVersion ;
360
+
353
361
// If there are no host processes to attach to or the user cancels selection, we get a null for the process id.
354
362
// This is not an error, just a request to stop the original "attach to" request.
355
363
// Testing against "undefined" is a HACK because I don't know how to make "Cancel" on quick pick loading
356
364
// to cancel on the VSCode side without sending an attachRequest with processId set to "undefined".
357
- if ( string . IsNullOrEmpty ( attachParams . ProcessId ) || ( attachParams . ProcessId == "undefined" ) )
365
+ if ( ! processIdIsSet && ! customPipeNameIsSet )
358
366
{
359
367
Logger . Write (
360
368
LogLevel . Normal ,
@@ -370,9 +378,6 @@ await requestContext.SendErrorAsync(
370
378
371
379
if ( attachParams . ComputerName != null )
372
380
{
373
- PowerShellVersionDetails runspaceVersion =
374
- _editorSession . PowerShellContext . CurrentRunspace . PowerShellVersion ;
375
-
376
381
if ( runspaceVersion . Version . Major < 4 )
377
382
{
378
383
await requestContext . SendErrorAsync (
@@ -403,16 +408,12 @@ await requestContext.SendErrorAsync(
403
408
_isRemoteAttach = true ;
404
409
}
405
410
406
- if ( int . TryParse ( attachParams . ProcessId , out int processId ) && ( processId > 0 ) )
411
+ if ( processIdIsSet && int . TryParse ( attachParams . ProcessId , out int processId ) && ( processId > 0 ) )
407
412
{
408
- PowerShellVersionDetails runspaceVersion =
409
- _editorSession . PowerShellContext . CurrentRunspace . PowerShellVersion ;
410
-
411
413
if ( runspaceVersion . Version . Major < 5 )
412
414
{
413
415
await requestContext . SendErrorAsync (
414
416
$ "Attaching to a process is only available with PowerShell 5 and higher (current session is { runspaceVersion . Version } ).") ;
415
-
416
417
return ;
417
418
}
418
419
@@ -427,20 +428,27 @@ await requestContext.SendErrorAsync(
427
428
428
429
return ;
429
430
}
431
+ }
432
+ else if ( customPipeNameIsSet )
433
+ {
434
+ if ( runspaceVersion . Version < _minVersionForCustomPipeName )
435
+ {
436
+ await requestContext . SendErrorAsync (
437
+ $ "Attaching to a process with CustomPipeName is only available with PowerShell 6.2 and higher (current session is { runspaceVersion . Version } ).") ;
438
+ return ;
439
+ }
430
440
431
- // Clear any existing breakpoints before proceeding
432
- await ClearSessionBreakpointsAsync ( ) ;
433
-
434
- // Execute the Debug-Runspace command but don't await it because it
435
- // will block the debug adapter initialization process. The
436
- // InitializedEvent will be sent as soon as the RunspaceChanged
437
- // event gets fired with the attached runspace.
438
- int runspaceId = attachParams . RunspaceId > 0 ? attachParams . RunspaceId : 1 ;
439
- _waitingForAttach = true ;
440
- Task nonAwaitedTask =
441
- _editorSession . PowerShellContext
442
- . ExecuteScriptStringAsync ( $ "\n Debug-Runspace -Id { runspaceId } ")
443
- . ContinueWith ( OnExecutionCompletedAsync ) ;
441
+ await _editorSession . PowerShellContext . ExecuteScriptStringAsync (
442
+ $ "Enter-PSHostProcess -CustomPipeName { attachParams . CustomPipeName } ",
443
+ errorMessages ) ;
444
+
445
+ if ( errorMessages . Length > 0 )
446
+ {
447
+ await requestContext . SendErrorAsync (
448
+ $ "Could not attach to process with CustomPipeName: '{ attachParams . CustomPipeName } '") ;
449
+
450
+ return ;
451
+ }
444
452
}
445
453
else
446
454
{
@@ -454,6 +462,19 @@ await requestContext.SendErrorAsync(
454
462
return ;
455
463
}
456
464
465
+ // Clear any existing breakpoints before proceeding
466
+ await ClearSessionBreakpointsAsync ( ) . ConfigureAwait ( continueOnCapturedContext : false ) ;
467
+
468
+ // Execute the Debug-Runspace command but don't await it because it
469
+ // will block the debug adapter initialization process. The
470
+ // InitializedEvent will be sent as soon as the RunspaceChanged
471
+ // event gets fired with the attached runspace.
472
+ int runspaceId = attachParams . RunspaceId > 0 ? attachParams . RunspaceId : 1 ;
473
+ _waitingForAttach = true ;
474
+ Task nonAwaitedTask = _editorSession . PowerShellContext
475
+ . ExecuteScriptStringAsync ( $ "\n Debug-Runspace -Id { runspaceId } ")
476
+ . ContinueWith ( OnExecutionCompletedAsync ) ;
477
+
457
478
await requestContext . SendResultAsync ( null ) ;
458
479
}
459
480
0 commit comments