@@ -35,6 +35,8 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns
35
35
{
36
36
internal const string DefaultPrompt = "> " ;
37
37
38
+ private static readonly PSCommand s_promptCommand = new PSCommand ( ) . AddCommand ( "prompt" ) ;
39
+
38
40
private static readonly PropertyInfo s_scriptDebuggerTriggerObjectProperty ;
39
41
40
42
private readonly ILoggerFactory _loggerFactory ;
@@ -474,7 +476,19 @@ public void InvokeDelegate(string representation, ExecutionOptions executionOpti
474
476
public IReadOnlyList < TResult > InvokePSCommand < TResult > ( PSCommand psCommand , PowerShellExecutionOptions executionOptions , CancellationToken cancellationToken )
475
477
{
476
478
SynchronousPowerShellTask < TResult > task = new ( _logger , this , psCommand , executionOptions , cancellationToken ) ;
477
- return task . ExecuteAndGetResult ( cancellationToken ) ;
479
+ try
480
+ {
481
+ return task . ExecuteAndGetResult ( cancellationToken ) ;
482
+ }
483
+ finally
484
+ {
485
+ // At the end of each PowerShell command we need to reset PowerShell 5.1's
486
+ // `TranscribeOnly` property to avoid a bug where output disappears.
487
+ if ( UI is EditorServicesConsolePSHostUserInterface ui )
488
+ {
489
+ ui . DisableTranscribeOnly ( ) ;
490
+ }
491
+ }
478
492
}
479
493
480
494
public void InvokePSCommand ( PSCommand psCommand , PowerShellExecutionOptions executionOptions , CancellationToken cancellationToken ) => InvokePSCommand < PSObject > ( psCommand , executionOptions , cancellationToken ) ;
@@ -1026,10 +1040,8 @@ internal string GetPrompt(CancellationToken cancellationToken)
1026
1040
string prompt = DefaultPrompt ;
1027
1041
try
1028
1042
{
1029
- // TODO: Should we cache PSCommands like this as static members?
1030
- PSCommand command = new PSCommand ( ) . AddCommand ( "prompt" ) ;
1031
1043
IReadOnlyList < string > results = InvokePSCommand < string > (
1032
- command ,
1044
+ s_promptCommand ,
1033
1045
executionOptions : new PowerShellExecutionOptions { ThrowOnError = false } ,
1034
1046
cancellationToken ) ;
1035
1047
@@ -1207,7 +1219,18 @@ private Runspace CreateInitialRunspace(InitialSessionState initialSessionState)
1207
1219
return runspace ;
1208
1220
}
1209
1221
1210
- // NOTE: This token is received from PSReadLine, and it _is_ the ReadKey cancellation token!
1222
+ /// <summary>
1223
+ /// This delegate is handed to PSReadLine and overrides similar logic within its `ReadKey`
1224
+ /// method. Essentially we're replacing PowerShell's `OnIdle` handler since the PowerShell
1225
+ /// engine isn't idle when we're sitting in PSReadLine's `ReadKey` loop. In our case we also
1226
+ /// use this idle time to process queued tasks by executing those that can run in the
1227
+ /// background, and canceling the foreground task if a queued tasks requires the foreground.
1228
+ /// Finally, if and only if we have to, we run an artificial pipeline to force PowerShell's
1229
+ /// own event processing.
1230
+ /// </summary>
1231
+ /// <param name="idleCancellationToken">
1232
+ /// This token is received from PSReadLine, and it is the ReadKey cancellation token!
1233
+ /// </param>
1211
1234
internal void OnPowerShellIdle ( CancellationToken idleCancellationToken )
1212
1235
{
1213
1236
IReadOnlyList < PSEventSubscriber > eventSubscribers = _mainRunspaceEngineIntrinsics . Events . Subscribers ;
@@ -1250,17 +1273,27 @@ internal void OnPowerShellIdle(CancellationToken idleCancellationToken)
1250
1273
1251
1274
// If we're executing a PowerShell task, we don't need to run an extra pipeline
1252
1275
// later for events.
1253
- runPipelineForEventProcessing = task is not ISynchronousPowerShellTask ;
1276
+ if ( task is ISynchronousPowerShellTask )
1277
+ {
1278
+ // We don't ever want to set this to true here, just skip if it had
1279
+ // previously been set true.
1280
+ runPipelineForEventProcessing = false ;
1281
+ }
1254
1282
ExecuteTaskSynchronously ( task , cancellationScope . CancellationToken ) ;
1255
1283
}
1256
1284
}
1257
1285
1258
1286
// We didn't end up executing anything in the background,
1259
1287
// so we need to run a small artificial pipeline instead
1260
- // to force event processing
1288
+ // to force event processing.
1261
1289
if ( runPipelineForEventProcessing )
1262
1290
{
1263
- InvokePSCommand ( new PSCommand ( ) . AddScript ( "0" , useLocalScope : true ) , executionOptions : null , CancellationToken . None ) ;
1291
+ InvokePSCommand (
1292
+ new PSCommand ( ) . AddScript (
1293
+ "[System.Diagnostics.DebuggerHidden()]param() 0" ,
1294
+ useLocalScope : true ) ,
1295
+ executionOptions : null ,
1296
+ CancellationToken . None ) ;
1264
1297
}
1265
1298
}
1266
1299
0 commit comments