@@ -520,7 +520,7 @@ await Task.Factory.StartNew<IEnumerable<TResult>>(
520
520
521
521
522
522
// Check if the runspace has changed
523
- this . PushRunspaceIfSessionChanged ( sessionDetails ) ;
523
+ this . UpdateRunspaceDetailsIfSessionChanged ( sessionDetails ) ;
524
524
}
525
525
526
526
// Dispose of the execution context
@@ -1290,9 +1290,12 @@ private SessionDetails GetSessionDetailsInDebugger()
1290
1290
return this . GetSessionDetails (
1291
1291
command =>
1292
1292
{
1293
+ // Use LastOrDefault to get the last item returned. This
1294
+ // is necessary because advanced prompt functions (like those
1295
+ // in posh-git) may return multiple objects in the result.
1293
1296
return
1294
1297
this . ExecuteCommandInDebugger < PSObject > ( command , false )
1295
- . FirstOrDefault ( ) ;
1298
+ . LastOrDefault ( ) ;
1296
1299
} ) ;
1297
1300
}
1298
1301
@@ -1331,7 +1334,7 @@ private void WritePromptInDebugger(SessionDetails sessionDetails, DebuggerStopEv
1331
1334
string promptPrefix = string . Empty ;
1332
1335
string promptString = sessionDetails . PromptString ;
1333
1336
1334
- if ( eventArgs != null )
1337
+ if ( eventArgs != null && promptString . Length > 0 )
1335
1338
{
1336
1339
// Is there a prompt prefix worth keeping?
1337
1340
const string promptSeparator = "]: " ;
@@ -1459,7 +1462,7 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
1459
1462
this . WritePromptInDebugger ( sessionDetails , e ) ;
1460
1463
1461
1464
// Push the current runspace if the session has changed
1462
- this . PushRunspaceIfSessionChanged ( sessionDetails ) ;
1465
+ this . UpdateRunspaceDetailsIfSessionChanged ( sessionDetails , isDebuggerStop : true ) ;
1463
1466
1464
1467
// Raise the event for the debugger service
1465
1468
this . DebuggerStop ? . Invoke ( sender , e ) ;
@@ -1586,6 +1589,13 @@ private void PushRunspace(RunspaceDetails newRunspaceDetails)
1586
1589
1587
1590
RunspaceDetails previousRunspace = this . CurrentRunspace ;
1588
1591
1592
+ if ( newRunspaceDetails . Context == RunspaceContext . DebuggedRunspace )
1593
+ {
1594
+ this . WriteOutput (
1595
+ $ "Entering debugged runspace on { newRunspaceDetails . Location . ToString ( ) . ToLower ( ) } machine { newRunspaceDetails . SessionDetails . ComputerName } ",
1596
+ true ) ;
1597
+ }
1598
+
1589
1599
// Switch out event handlers if necessary
1590
1600
if ( CheckIfRunspaceNeedsEventHandlers ( newRunspaceDetails ) )
1591
1601
{
@@ -1604,119 +1614,63 @@ private void PushRunspace(RunspaceDetails newRunspaceDetails)
1604
1614
this . CurrentRunspace ) ) ;
1605
1615
}
1606
1616
1607
- private void PushRunspaceIfSessionChanged ( SessionDetails sessionDetails , bool isDebuggerStop = false )
1617
+ private void UpdateRunspaceDetailsIfSessionChanged ( SessionDetails sessionDetails , bool isDebuggerStop = false )
1608
1618
{
1609
- bool needsPop = false ;
1610
- RunspaceContext ? newRunspaceContext = null ;
1619
+ RunspaceDetails newRunspaceDetails = null ;
1611
1620
1612
- if ( this . CurrentRunspace . Location == RunspaceLocation . Local &&
1613
- ! string . Equals (
1614
- this . CurrentRunspace . SessionDetails . ComputerName ,
1615
- sessionDetails . ComputerName ,
1616
- StringComparison . CurrentCultureIgnoreCase ) )
1621
+ // If we've exited an entered process or debugged runspace, pop what we've
1622
+ // got before we evaluate where we're at
1623
+ if (
1624
+ ( this . CurrentRunspace . Context == RunspaceContext . DebuggedRunspace &&
1625
+ this . CurrentRunspace . SessionDetails . InstanceId != sessionDetails . InstanceId ) ||
1626
+ ( this . CurrentRunspace . Context == RunspaceContext . EnteredProcess &&
1627
+ this . CurrentRunspace . SessionDetails . ProcessId != sessionDetails . ProcessId ) )
1617
1628
{
1618
- // This is a special case scenario when debugging remote ScriptBlocks.
1619
- // Normally entering a remote session will cause PushRunspace to be
1620
- // called. If we suddenly find ourselves in a different machine without
1621
- // a prior PushRunspace call it means that the debugger has stepped into
1622
- // the execution of a remote ScriptBlock.
1623
- this . PushRunspace (
1624
- RunspaceDetails . CreateFromDebugger (
1625
- this . CurrentRunspace ,
1626
- RunspaceLocation . Remote ,
1627
- RunspaceContext . DebuggedRunspace ,
1628
- sessionDetails ) ) ;
1629
+ this . PopRunspace ( ) ;
1629
1630
}
1630
- else if (
1631
- this . CurrentRunspace . Location == RunspaceLocation . Remote &&
1632
- ! string . Equals (
1633
- this . CurrentRunspace . SessionDetails . ComputerName ,
1634
- sessionDetails . ComputerName ,
1635
- StringComparison . CurrentCultureIgnoreCase ) )
1636
- {
1637
- // This is the "exit" case of the previous case. If we hit a breakpoint
1638
- // and we're suddenly in a different runspace, react accordingly. This can
1639
- // happen if we are now debugging the same ScriptBlock on another machine or
1640
- // if we are now back in the original local runspace.
1641
1631
1642
- // First, pop the remote runspace in either case
1643
- this . PopRunspace ( ) ;
1632
+ // Are we in a new session that the PushRunspace command won't
1633
+ // notify us about?
1634
+ //
1635
+ // Possible cases:
1636
+ // - Debugged runspace in a local or remote session
1637
+ // - Entered process in a remote session
1638
+ //
1639
+ // We don't need additional logic to check for the cases that
1640
+ // PowerShell would have notified us about because the CurrentRunspace
1641
+ // will already be updated by PowerShell by the time we reach
1642
+ // these checks.
1644
1643
1645
- // If the new computer name doesn't match that of the current machine, we're
1646
- // on another remote computer
1647
- if ( ! string . Equals (
1644
+ if ( this . CurrentRunspace . SessionDetails . InstanceId != sessionDetails . InstanceId && isDebuggerStop )
1645
+ {
1646
+ // Are we on a local or remote computer?
1647
+ bool differentComputer =
1648
+ ! string . Equals (
1648
1649
sessionDetails . ComputerName ,
1649
1650
this . initialRunspace . SessionDetails . ComputerName ,
1650
- StringComparison . CurrentCultureIgnoreCase ) )
1651
- {
1652
- // Push the runspace for another remote session
1653
- this . PushRunspace (
1654
- RunspaceDetails . CreateFromDebugger (
1655
- this . CurrentRunspace ,
1656
- RunspaceLocation . Remote ,
1657
- RunspaceContext . DebuggedRunspace ,
1658
- sessionDetails ) ) ;
1659
- }
1660
- }
1661
-
1662
- // This logic checks for any session change that is never communicated
1663
- // via a call to PushRunspace:
1664
- // - Remote session entering a different process
1665
- // - Local or remote session debugging a runspace in the current process
1666
- // - Local or remote session debugging a runspace in the current process
1651
+ StringComparison . CurrentCultureIgnoreCase ) ;
1667
1652
1668
- if ( this . CurrentRunspace . Location == RunspaceLocation . Local &&
1669
- this . CurrentRunspace . SessionDetails . InstanceId != sessionDetails . InstanceId )
1670
- {
1671
- // Did we start or stop debugging a runspace?
1672
- if ( this . CurrentRunspace . Context != RunspaceContext . DebuggedRunspace )
1673
- {
1674
- newRunspaceContext = RunspaceContext . DebuggedRunspace ;
1675
- }
1676
- else
1677
- {
1678
- needsPop = true ;
1679
- }
1680
- }
1681
- else if ( this . CurrentRunspace . Location == RunspaceLocation . Remote )
1682
- {
1683
- if ( this . CurrentRunspace . SessionDetails . ProcessId != sessionDetails . ProcessId )
1684
- {
1685
- // Did we attach to or detach from a process?
1686
- if ( this . CurrentRunspace . Context != RunspaceContext . EnteredProcess )
1687
- {
1688
- newRunspaceContext = RunspaceContext . EnteredProcess ;
1689
- }
1690
- else
1691
- {
1692
- needsPop = true ;
1693
- }
1694
- }
1695
- else if ( this . CurrentRunspace . SessionDetails . InstanceId != sessionDetails . InstanceId )
1696
- {
1697
- // Debugging a different runspace
1698
- if ( this . CurrentRunspace . Context != RunspaceContext . DebuggedRunspace )
1699
- {
1700
- newRunspaceContext = RunspaceContext . DebuggedRunspace ;
1701
- }
1702
- else
1703
- {
1704
- needsPop = true ;
1705
- }
1706
- }
1653
+ // We started debugging a runspace
1654
+ newRunspaceDetails =
1655
+ RunspaceDetails . CreateFromDebugger (
1656
+ this . CurrentRunspace ,
1657
+ differentComputer ? RunspaceLocation . Remote : RunspaceLocation . Local ,
1658
+ RunspaceContext . DebuggedRunspace ,
1659
+ sessionDetails ) ;
1707
1660
}
1708
-
1709
- if ( newRunspaceContext . HasValue )
1661
+ else if ( this . CurrentRunspace . SessionDetails . ProcessId != sessionDetails . ProcessId )
1710
1662
{
1711
- this . PushRunspace (
1663
+ // We entered a different PowerShell host process
1664
+ newRunspaceDetails =
1712
1665
RunspaceDetails . CreateFromContext (
1713
1666
this . CurrentRunspace ,
1714
- newRunspaceContext . Value ,
1715
- sessionDetails ) ) ;
1667
+ RunspaceContext . EnteredProcess ,
1668
+ sessionDetails ) ;
1716
1669
}
1717
- else if ( needsPop )
1670
+
1671
+ if ( newRunspaceDetails != null )
1718
1672
{
1719
- this . PopRunspace ( ) ;
1673
+ this . PushRunspace ( newRunspaceDetails ) ;
1720
1674
}
1721
1675
}
1722
1676
@@ -1733,6 +1687,13 @@ private void PopRunspace()
1733
1687
LogLevel . Verbose ,
1734
1688
$ "Popping { previousRunspace . Location } ({ previousRunspace . Context } ), new runspace is { this . CurrentRunspace . Location } ({ this . CurrentRunspace . Context } ), connection: { this . CurrentRunspace . ConnectionString } ") ;
1735
1689
1690
+ if ( previousRunspace . Context == RunspaceContext . DebuggedRunspace )
1691
+ {
1692
+ this . WriteOutput (
1693
+ $ "Leaving debugged runspace on { previousRunspace . Location . ToString ( ) . ToLower ( ) } machine { previousRunspace . SessionDetails . ComputerName } ",
1694
+ true ) ;
1695
+ }
1696
+
1736
1697
// Switch out event handlers if necessary
1737
1698
if ( CheckIfRunspaceNeedsEventHandlers ( previousRunspace ) )
1738
1699
{
0 commit comments