@@ -520,7 +520,7 @@ await Task.Factory.StartNew<IEnumerable<TResult>>(
520520
521521
522522 // Check if the runspace has changed
523- this . PushRunspaceIfSessionChanged ( sessionDetails ) ;
523+ this . UpdateRunspaceDetailsIfSessionChanged ( sessionDetails ) ;
524524 }
525525
526526 // Dispose of the execution context
@@ -1290,9 +1290,12 @@ private SessionDetails GetSessionDetailsInDebugger()
12901290 return this . GetSessionDetails (
12911291 command =>
12921292 {
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.
12931296 return
12941297 this . ExecuteCommandInDebugger < PSObject > ( command , false )
1295- . FirstOrDefault ( ) ;
1298+ . LastOrDefault ( ) ;
12961299 } ) ;
12971300 }
12981301
@@ -1331,7 +1334,7 @@ private void WritePromptInDebugger(SessionDetails sessionDetails, DebuggerStopEv
13311334 string promptPrefix = string . Empty ;
13321335 string promptString = sessionDetails . PromptString ;
13331336
1334- if ( eventArgs != null )
1337+ if ( eventArgs != null && promptString . Length > 0 )
13351338 {
13361339 // Is there a prompt prefix worth keeping?
13371340 const string promptSeparator = "]: " ;
@@ -1459,7 +1462,7 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
14591462 this . WritePromptInDebugger ( sessionDetails , e ) ;
14601463
14611464 // Push the current runspace if the session has changed
1462- this . PushRunspaceIfSessionChanged ( sessionDetails ) ;
1465+ this . UpdateRunspaceDetailsIfSessionChanged ( sessionDetails , isDebuggerStop : true ) ;
14631466
14641467 // Raise the event for the debugger service
14651468 this . DebuggerStop ? . Invoke ( sender , e ) ;
@@ -1586,6 +1589,13 @@ private void PushRunspace(RunspaceDetails newRunspaceDetails)
15861589
15871590 RunspaceDetails previousRunspace = this . CurrentRunspace ;
15881591
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+
15891599 // Switch out event handlers if necessary
15901600 if ( CheckIfRunspaceNeedsEventHandlers ( newRunspaceDetails ) )
15911601 {
@@ -1604,119 +1614,63 @@ private void PushRunspace(RunspaceDetails newRunspaceDetails)
16041614 this . CurrentRunspace ) ) ;
16051615 }
16061616
1607- private void PushRunspaceIfSessionChanged ( SessionDetails sessionDetails , bool isDebuggerStop = false )
1617+ private void UpdateRunspaceDetailsIfSessionChanged ( SessionDetails sessionDetails , bool isDebuggerStop = false )
16081618 {
1609- bool needsPop = false ;
1610- RunspaceContext ? newRunspaceContext = null ;
1619+ RunspaceDetails newRunspaceDetails = null ;
16111620
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 ) )
16171628 {
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 ( ) ;
16291630 }
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.
16411631
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.
16441643
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 (
16481649 sessionDetails . ComputerName ,
16491650 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 ) ;
16671652
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 ) ;
17071660 }
1708-
1709- if ( newRunspaceContext . HasValue )
1661+ else if ( this . CurrentRunspace . SessionDetails . ProcessId != sessionDetails . ProcessId )
17101662 {
1711- this . PushRunspace (
1663+ // We entered a different PowerShell host process
1664+ newRunspaceDetails =
17121665 RunspaceDetails . CreateFromContext (
17131666 this . CurrentRunspace ,
1714- newRunspaceContext . Value ,
1715- sessionDetails ) ) ;
1667+ RunspaceContext . EnteredProcess ,
1668+ sessionDetails ) ;
17161669 }
1717- else if ( needsPop )
1670+
1671+ if ( newRunspaceDetails != null )
17181672 {
1719- this . PopRunspace ( ) ;
1673+ this . PushRunspace ( newRunspaceDetails ) ;
17201674 }
17211675 }
17221676
@@ -1733,6 +1687,13 @@ private void PopRunspace()
17331687 LogLevel . Verbose ,
17341688 $ "Popping { previousRunspace . Location } ({ previousRunspace . Context } ), new runspace is { this . CurrentRunspace . Location } ({ this . CurrentRunspace . Context } ), connection: { this . CurrentRunspace . ConnectionString } ") ;
17351689
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+
17361697 // Switch out event handlers if necessary
17371698 if ( CheckIfRunspaceNeedsEventHandlers ( previousRunspace ) )
17381699 {
0 commit comments