Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1071,18 +1071,16 @@ public override void NotifyBeginApplication()
{
lock (hostGlobalLock)
{
++_beginApplicationNotifyCount;
if (_beginApplicationNotifyCount == 1)
if (++_beginApplicationNotifyCount == 1)
{
// save the window title when first notified.

// Save the window title when first notified.
_savedWindowTitle = ui.RawUI.WindowTitle;
#if !UNIX
if (_initialConsoleMode != ConsoleControl.ConsoleModes.Unknown)
{
var activeScreenBufferHandle = ConsoleControl.GetActiveScreenBufferHandle();
_savedConsoleMode = ConsoleControl.GetMode(activeScreenBufferHandle);
ConsoleControl.SetMode(activeScreenBufferHandle, _initialConsoleMode);
var outputHandle = ConsoleControl.GetActiveScreenBufferHandle();
_savedConsoleMode = ConsoleControl.GetMode(outputHandle);
ConsoleControl.SetMode(outputHandle, _initialConsoleMode);
}
#endif
}
Expand All @@ -1097,17 +1095,26 @@ public override void NotifyEndApplication()
{
lock (hostGlobalLock)
{
Dbg.Assert(_beginApplicationNotifyCount > 0, "Not running an executable - NotifyBeginApplication was not called!");
--_beginApplicationNotifyCount;
if (_beginApplicationNotifyCount == 0)
if (--_beginApplicationNotifyCount == 0)
{
// restore the window title when the last application started has ended.

// Restore the window title when the last application started has ended.
ui.RawUI.WindowTitle = _savedWindowTitle;
#if !UNIX
if (_savedConsoleMode != ConsoleControl.ConsoleModes.Unknown)
{
ConsoleControl.SetMode(ConsoleControl.GetActiveScreenBufferHandle(), _savedConsoleMode);
if (_savedConsoleMode.HasFlag(ConsoleControl.ConsoleModes.VirtualTerminal))
{
// If the console output mode we just set already has 'VirtualTerminal' turned on,
// we don't need to try turn on the VT mode separately.
return;
}
}

if (ui.SupportsVirtualTerminal)
{
// Re-enable VT mode if it was previously enabled, as a native command may have turned it off.
ui.TryTurnOnVirtualTerminal();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Interesting, is such console operations expensive?
In line 1105 we have already requested a handle and set mode, now TryTurnOnVirtualTerminal does the operations again. It seems we could do perf optimization.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very likely not expensive, especially if this is done only after native command execution. The handle is already cached, GetActiveScreenBufferHandle() returns a cached output handle.

}
#endif
}
Expand Down Expand Up @@ -2452,14 +2459,6 @@ internal void Run(bool inputLoopIsNested)

while (!_parent.ShouldEndSession && !_shouldExit)
{
#if !UNIX
if (ui.SupportsVirtualTerminal)
{
// need to re-enable VT mode if it was previously enabled as native commands may have turned it off
ui.TryTurnOnVtMode();
}
#endif

try
{
_parent._isRunningPromptLoop = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,28 +87,34 @@ internal ConsoleHostUserInterface(ConsoleHost parent)

if (SupportsVirtualTerminal)
{
SupportsVirtualTerminal = TryTurnOnVtMode();
SupportsVirtualTerminal = TryTurnOnVirtualTerminal();
}
}

internal bool TryTurnOnVtMode()
internal bool TryTurnOnVirtualTerminal()
{
#if UNIX
return true;
#else
try
{
// Turn on virtual terminal if possible.

// This might throw - not sure how exactly (no console), but if it does, we shouldn't fail to start.
var handle = ConsoleControl.GetActiveScreenBufferHandle();
var m = ConsoleControl.GetMode(handle);
if (ConsoleControl.NativeMethods.SetConsoleMode(handle.DangerousGetHandle(), (uint)(m | ConsoleControl.ConsoleModes.VirtualTerminal)))
var outputHandle = ConsoleControl.GetActiveScreenBufferHandle();
var outputMode = ConsoleControl.GetMode(outputHandle);

if (outputMode.HasFlag(ConsoleControl.ConsoleModes.VirtualTerminal))
{
return true;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the outputMode already has VirtualTerminal enabled, no need to set the mode again.


outputMode |= ConsoleControl.ConsoleModes.VirtualTerminal;
if (ConsoleControl.NativeMethods.SetConsoleMode(outputHandle.DangerousGetHandle(), (uint)outputMode))
{
// We only know if vt100 is supported if the previous call actually set the new flag, older
// systems ignore the setting.
m = ConsoleControl.GetMode(handle);
return (m & ConsoleControl.ConsoleModes.VirtualTerminal) != 0;
outputMode = ConsoleControl.GetMode(outputHandle);
return outputMode.HasFlag(ConsoleControl.ConsoleModes.VirtualTerminal);
}
}
catch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,15 +545,14 @@ private void InitNativeProcess()
Exception exceptionToRethrow = null;
try
{
// If this process is being run standalone, tell the host, which might want
// to save off the window title or other such state as might be tweaked by
// the native process
// Before start the executable, tell the host, which might want to save off the
// window title or other such state as might be tweaked by the native process.
Command.Context.EngineHostInterface.NotifyBeginApplication();
_hasNotifiedBeginApplication = true;

if (_runStandAlone)
{
this.Command.Context.EngineHostInterface.NotifyBeginApplication();
_hasNotifiedBeginApplication = true;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a native process tweaks the window title, it will do so no matter it's running StandAlone or in a pipeline. So, we should actually always call NotifyBeginApplication and NotifyEndApplication before and after running a native command. Therefore, I moved this code out of the if (_runStandAlone) block.


// Also, store the Raw UI coordinates so that we can scrape the screen after
// Store the Raw UI coordinates so that we can scrape the screen after
// if we are transcribing.
if (_isTranscribing && (s_supportScreenScrape == true))
{
Expand Down Expand Up @@ -1166,7 +1165,7 @@ private void CleanUp()
// We need to call 'NotifyEndApplication' as appropriate during cleanup
if (_hasNotifiedBeginApplication)
{
this.Command.Context.EngineHostInterface.NotifyEndApplication();
Command.Context.EngineHostInterface.NotifyEndApplication();
}

try
Expand Down