@@ -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 ;
@@ -344,11 +346,17 @@ protected async Task HandleAttachRequest(
344
346
345
347
RegisterEventHandlers ( ) ;
346
348
349
+ bool processIdIsSet = ! string . IsNullOrEmpty ( attachParams . ProcessId ) && attachParams . ProcessId != "undefined" ;
350
+ bool customPipeNameIsSet = ! string . IsNullOrEmpty ( attachParams . CustomPipeName ) && attachParams . CustomPipeName != "undefined" ;
351
+
352
+ PowerShellVersionDetails runspaceVersion =
353
+ _editorSession . PowerShellContext . CurrentRunspace . PowerShellVersion ;
354
+
347
355
// If there are no host processes to attach to or the user cancels selection, we get a null for the process id.
348
356
// This is not an error, just a request to stop the original "attach to" request.
349
357
// Testing against "undefined" is a HACK because I don't know how to make "Cancel" on quick pick loading
350
358
// to cancel on the VSCode side without sending an attachRequest with processId set to "undefined".
351
- if ( string . IsNullOrEmpty ( attachParams . ProcessId ) || ( attachParams . ProcessId == "undefined" ) )
359
+ if ( ! processIdIsSet && ! customPipeNameIsSet )
352
360
{
353
361
Logger . Write (
354
362
LogLevel . Normal ,
@@ -364,9 +372,6 @@ await requestContext.SendError(
364
372
365
373
if ( attachParams . ComputerName != null )
366
374
{
367
- PowerShellVersionDetails runspaceVersion =
368
- _editorSession . PowerShellContext . CurrentRunspace . PowerShellVersion ;
369
-
370
375
if ( runspaceVersion . Version . Major < 4 )
371
376
{
372
377
await requestContext . SendError (
@@ -397,16 +402,12 @@ await requestContext.SendError(
397
402
_isRemoteAttach = true ;
398
403
}
399
404
400
- if ( int . TryParse ( attachParams . ProcessId , out int processId ) && ( processId > 0 ) )
405
+ if ( processIdIsSet && int . TryParse ( attachParams . ProcessId , out int processId ) && ( processId > 0 ) )
401
406
{
402
- PowerShellVersionDetails runspaceVersion =
403
- _editorSession . PowerShellContext . CurrentRunspace . PowerShellVersion ;
404
-
405
407
if ( runspaceVersion . Version . Major < 5 )
406
408
{
407
409
await requestContext . SendError (
408
410
$ "Attaching to a process is only available with PowerShell 5 and higher (current session is { runspaceVersion . Version } ).") ;
409
-
410
411
return ;
411
412
}
412
413
@@ -421,20 +422,27 @@ await requestContext.SendError(
421
422
422
423
return ;
423
424
}
425
+ }
426
+ else if ( customPipeNameIsSet )
427
+ {
428
+ if ( runspaceVersion . Version < _minVersionForCustomPipeName )
429
+ {
430
+ await requestContext . SendError (
431
+ $ "Attaching to a process with CustomPipeName is only available with PowerShell 6.2 and higher (current session is { runspaceVersion . Version } ).") ;
432
+ return ;
433
+ }
424
434
425
- // Clear any existing breakpoints before proceeding
426
- await ClearSessionBreakpoints ( ) ;
427
-
428
- // Execute the Debug-Runspace command but don't await it because it
429
- // will block the debug adapter initialization process. The
430
- // InitializedEvent will be sent as soon as the RunspaceChanged
431
- // event gets fired with the attached runspace.
432
- int runspaceId = attachParams . RunspaceId > 0 ? attachParams . RunspaceId : 1 ;
433
- _waitingForAttach = true ;
434
- Task nonAwaitedTask =
435
- _editorSession . PowerShellContext
436
- . ExecuteScriptString ( $ "\n Debug-Runspace -Id { runspaceId } ")
437
- . ContinueWith ( OnExecutionCompleted ) ;
435
+ await _editorSession . PowerShellContext . ExecuteScriptString (
436
+ $ "Enter-PSHostProcess -CustomPipeName { attachParams . CustomPipeName } ",
437
+ errorMessages ) ;
438
+
439
+ if ( errorMessages . Length > 0 )
440
+ {
441
+ await requestContext . SendError (
442
+ $ "Could not attach to process with CustomPipeName: '{ attachParams . CustomPipeName } '") ;
443
+
444
+ return ;
445
+ }
438
446
}
439
447
else
440
448
{
@@ -448,6 +456,19 @@ await requestContext.SendError(
448
456
return ;
449
457
}
450
458
459
+ // Clear any existing breakpoints before proceeding
460
+ await ClearSessionBreakpoints ( ) . ConfigureAwait ( continueOnCapturedContext : false ) ;
461
+
462
+ // Execute the Debug-Runspace command but don't await it because it
463
+ // will block the debug adapter initialization process. The
464
+ // InitializedEvent will be sent as soon as the RunspaceChanged
465
+ // event gets fired with the attached runspace.
466
+ int runspaceId = attachParams . RunspaceId > 0 ? attachParams . RunspaceId : 1 ;
467
+ _waitingForAttach = true ;
468
+ Task nonAwaitedTask = _editorSession . PowerShellContext
469
+ . ExecuteScriptString ( $ "\n Debug-Runspace -Id { runspaceId } ")
470
+ . ContinueWith ( OnExecutionCompleted ) ;
471
+
451
472
await requestContext . SendResult ( null ) ;
452
473
}
453
474
0 commit comments