OCGV: Sometimes exits as soon as arrow key is pressed
Prerequisites
- [X] Write a descriptive title.
- [X] Make sure you are able to repro it on the latest version
- [X] Search the existing issues.
Steps to reproduce
This one seems a bit random but ive managed to isolate it a block of code i think can trigger it sometimes. It might take a good few runs of the below code to get it to happen.
$list=@(1..100)
$count =0
do{
[PSCustomObject]$platform = $list | Out-consoleGridView -verbose -OutputMode Single -Title $count
$platform.name.split()
Write-Host "fgfg"
$count ++
}
while ($count -lt 3)
Write-Host "gh"
I know the split will error on this by design as it seems to help trigger this more often.
What should happen is when running this loop with F8 in VS code sometime the first iteration will skip when you try to arrow down to select one in the list.
Version used is master compiled from source but same exact thing happens with 0.6.2
Expected behavior
OCGV not to skip
Actual behavior
occasionally OCGV exits without allowing you to select anything
Error details
Exception :
Type : System.Management.Automation.RuntimeException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : You cannot call a method on a null-valued expression.
HResult : -2146233087
CategoryInfo : InvalidOperation: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : InvokeMethodOnNull
InvocationInfo :
ScriptLineNumber : 3
OffsetInLine : 1
HistoryId : -1
Line : $platform.name.split()
PositionMessage : At line:3 char:1
+ $platform.name.split()
+ ~~~~~~~~~~~~~~~~~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 3
TargetSite : System.Object CallSite.Target(System.Runtime.CompilerServices.Closure,
System.Runtime.CompilerServices.CallSite, System.Object)
Message : You cannot call a method on a null-valued expression.
Data : System.Collections.ListDictionaryInternal
Source : Anonymously Hosted DynamicMethods Assembly
HResult : -2146233087
StackTrace :
at CallSite.Target(Closure , CallSite , Object )
at System.Management.Automation.Interpreter.DynamicInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
CategoryInfo : InvalidOperation: (:) [], RuntimeException
FullyQualifiedErrorId : InvokeMethodOnNull
InvocationInfo :
ScriptLineNumber : 3
OffsetInLine : 1
HistoryId : -1
Line : $platform.name.split()
PositionMessage : At line:3 char:1
+ $platform.name.split()
+ ~~~~~~~~~~~~~~~~~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 3
Environment data
Name Value
---- -----
PSVersion 7.2.6
PSEdition Core
GitCommitId 7.2.6
OS Darwin 21.6.0 Darwin Kernel Version 21.6.0: Wed Aug 10 14:28:23 PDT 2022; root:xnu-8020.141.5~2…
Platform Unix
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Version
0.6.3
Visuals

I've tried dozens of times and I can't get this to repro.
Can you still repro it with what's in master?
Note that because of #93 the initial behaviour is different than when you first reported this and it might be masking the issue?
Ive just cloned master and built the module, I can still trigger this, Not sure if its relevant but im using a mac.
Ive triggered it by doing the following
New pwsh console, Import module run script above, spam the esc key more times than required to exit the loop. Run the loop again, the first try should skip, If in-fact it seems if the esc key is hit too many times when displaying OCGV it will cause the OCGV to skip.
This is not whats triggered it in larger scripts this was a part of however this does seem to somewhat reliably produce the bug.
Hope this helps, If i can be of anymore assistance please do let me know
I cannot repro this on Debian in WSL or Windows. I do not have access to a Mac.
- New
pwsh - Paste script above
- As soon as OCGV shows, hit ESC a bunch of times
- OCGV will show 3 times in succession
- Paste script above again
-
- OCGV will show 3 times in succession
Is this how you repo it?
Thats correct, after 3, if you try to scroll down to select an item in OCGV it should skip
Still can't repo on Windows or Debian (Windows Terminal). Also tried within VS Code's Terminal.
@bdisp or @tznind - do either of you have a Mac you can try to repro this on?
Just managed to trigger this on WSL in Windows Terminal from master
---- -----
PSVersion 7.2.6
PSEdition Core
GitCommitId 7.2.6
OS Linux 5.10.102.1-microsoft-standard-WSL2 #1 SMP Wed Mar 2 00:30:59 UTC 2022
Platform Unix
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
ModuleType Version PreRelease Name ExportedCommands
---------- ------- ---------- ---- ----------------
Binary 0.7.2 Microsoft.PowerShell.ConsoleGuiToo… {Out-ConsoleGridView, ocgv}

steps to repro
Paste in the code, hit ESC 3 or 4 time rapidly during run 0, you should then find when the next OCGV pop ups, try using arrow keys to move down the list. It should skip and go to the next run without letting you select anything.
Got it. Repo'd on Debian. But not Windows.
I have no ideas on what the cause could be. The stack trace you posted points to something involving PowerShell:
Exception :
Type : System.Management.Automation.RuntimeException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : You cannot call a method on a null-valued expression.
HResult : -2146233087
CategoryInfo : InvalidOperation: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : InvokeMethodOnNull
InvocationInfo :
ScriptLineNumber : 3
OffsetInLine : 1
HistoryId : -1
Line : $platform.name.split()
How did you collect that stack trace?
Glad you managed to reproduce it!
The stack was from Get-Error not entirely sure it relates to this problem vs something else.
I tested on Ubuntu (WSL) and I can reproduce the error, but without open the warning window. By symptoms, it seems that the OCGV is not calling Application.Shutdown when the ESC key is pressed. On Windows there are no problem with this but with Linux and Mac, probably, will causing the OCGV not totally destroyed and re-created. The main cause for the ESC is not working properly in Linux is because of the delay used in ncurses to check if there some other escapes sequences associated. That why the OCGV is still opened after pressing three times. Another issue I'm facing is the OCGV changing his color when I re-run the script again.
Another issue I'm facing is the OCGV changing his color when I re-run the script again.
@BDisp Do you think this is related? I don't see it. Should it be a separate issue?
I tested on Ubuntu (WSL) and I can reproduce the error, but without open the warning window. By symptoms, it seems that the OCGV is not calling
Application.Shutdownwhen the ESC key is pressed. On Windows there are no problem with this but with Linux and Mac, probably, will causing the OCGV not totally destroyed and re-created. The main cause for the ESC is not working properly in Linux is because of the delay used in ncurses to check if there some other escapes sequences associated. That why the OCGV is still opened after pressing three times.
Odd that you're not seeing Application.Shutdown being called...
...
// Run the GUI.
Application.Run();
Application.Shutdown();
// Called when ESC is pressed:
private void Close()
{
_cancelled = true;
Application.RequestStop();
}
Another issue I'm facing is the OCGV changing his color when I re-run the script again.
@BDisp Do you think this is related? I don't see it. Should it be a separate issue?
I tested with the above code provided. Should that code explicit call Application.Shutdown? Since the OCGV already call, sorry my mistake.
Another issue I'm facing is the OCGV changing his color when I re-run the script again.
@BDisp Do you think this is related? I don't see it. Should it be a separate issue?
I tested with the above code provided. Should that code explicit call Application.Shutdown? Since the OCGV already call, sorry my mistake.
That code is the code in OCGV; I pasted it to show why I think OCGV is actually calling Shutdown.
That code is the code in OCGV; I pasted it to show why I think OCGV is actually calling Shutdown.
$list=@(1..100)
$count =0
do{
[PSCustomObject]$platform = $list | Out-consoleGridView -verbose -OutputMode Single -Title $count
$platform.name.split()
Write-Host "fgfg"
$count ++
}
while ($count -lt 3)
Write-Host "gh"
Sorry, I meaning if this code should call Application.Shutdown, since it's calling OCGV three times?
Sorry, I meaning if this code should call
Application.Shutdown, since it's calling OCGV three times?
No, OCGV is a PowerShell Cmdlet that calls Application.Shutdown (per the code I pasted above) each time.
I just instrumented OCGV and using this version of the script, it's clear Shutdown is being called. So that's not the cause of this issue.
Write-Host "start of script"
$list=@(1..100)
$count =0
do{
$list | Out-consoleGridView -Verbose -OutputMode Single -Title $count
#$platform.name.split()
Write-Host "ocgv exited"
$count ++
}
while ($count -lt 3)
Write-Host "end of script"
@Tigger2014 - did this issue ever reproduce for you when the ESC key was not involved?
Do you have repro that involves ONLY the arrow key causing the cmdlet to exit?
@Tigger2014 - did this issue ever reproduce for you when the ESC key was not involved?
Do you have repro that involves ONLY the arrow key causing the cmdlet to exit?
I've seen it happen when i think the esc key wasn't involved but it's not code i can share unfortunately. Im also not 100% sure ESC wasn't touched.
Ok, I'll keep poking around.
My current suspicion is that @BDisp was on the right track and this has something to do with the way the Terminal.Gui ncurses driver handles the ESC key.
So, if you figure out how to repro it WITHOUT involving the ESC key please yell!
The other potential culprit is the "hack" in OCGV that resets the "Application Cursor" by emitting an ANSI ESC sequence when it closes:
https://github.com/PowerShell/GraphicalTools/blob/76dbfcef5c099b8e4a73a55fde6e3f0ff37fb15b/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs#L403
The thought (which may be way off base) is that this ESC sequence is getting echo'd back and causing OCGV to think the user pressed the ESC key.
@tig see the End method on CursesDriver where I use some escape sequences to restore the terminal on exit. Another solution is OCGV using NetDriver on Linux and Mac.
The other potential culprit is the "hack" in OCGV that resets the "Application Cursor" by emitting an ANSI ESC sequence when it closes:
https://github.com/PowerShell/GraphicalTools/blob/76dbfcef5c099b8e4a73a55fde6e3f0ff37fb15b/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs#L403
The thought (which may be way off base) is that this ESC sequence is getting echo'd back and causing OCGV to think the user pressed the ESC key.
Thinking better I bet that this is really the culprit, because the CursesDriver already do all clean up on exit to restore the terminal. Sending more escape sequences after exit will getting echoed back and reinitialize the CursesDriver again, like it never close.
Try remove it.
The other potential culprit is the "hack" in OCGV that resets the "Application Cursor" by emitting an ANSI ESC sequence when it closes: https://github.com/PowerShell/GraphicalTools/blob/76dbfcef5c099b8e4a73a55fde6e3f0ff37fb15b/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs#L403
The thought (which may be way off base) is that this ESC sequence is getting echo'd back and causing OCGV to think the user pressed the ESC key.
Thinking better I bet that this is really the culprit, because the
CursesDriveralready do all clean up on exit to restore the terminal. Sending more escape sequences after exit will getting echoed back and reinitialize theCursesDriveragain, like it never close. Try remove it.
Just commented out that line, Still happens unfortunately
Further to this, not sure it helps much but swapping ESC for a for example, i cant reproduce this.
https://github.com/PowerShell/GraphicalTools/blob/master/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs#L214
Seems this could be related to your suggestion
. The main cause for the ESC is not working properly in Linux is because of the delay used in ncurses to check if there some other escapes sequences associated.
Seems this could be related to your suggestion
. The main cause for the ESC is not working properly in Linux is because of the delay used in ncurses to check if there some other escapes sequences associated.
For sure that is. Unfortunately, that interval delay is necessary to unix process all the Ansi Esc Sequence. If no more char exist after the delay then assumes that only the Esc key was pressed and process it alone, otherwise continuous reading all chars to get a key combination, like Alt, Ctrl-Alt or a mouse event, whatever. Maybe lowing down the delay to check if it work without affect his functionality.
Found these docs (see below) on the feature I think you are talking about @BDisp. Looks like you can change the setting at runtime with an Environment Variable e.g.
export ESCDELAY=1
Set time taken to release an Escape keystroke to 1ms
I tested setting it to 2000 and saw Esc being delayed so it seems to work.
Although from the docs docs it sounds like the same setting interacts with mouse events:
Environment
The following environment symbols are useful for customizing the runtime behavior of the ncurses library. The most important ones have been already discussed in detail.
[...]
ESCDELAY Specifies the total time, in milliseconds, for which ncurses will await a character sequence, e.g., a function key. The default value, 1000 milliseconds, is enough for most uses. However, it is made a variable to accommodate unusual applications. The most common instance where you may wish to change this value is to work with slow hosts, e.g., running on a network. If the host cannot read characters rapidly enough, it will have the same effect as if the terminal did not send characters rapidly enough. The library will still see a timeout.
Note that xterm mouse events are built up from character sequences received from the xterm. If your application makes heavy use of multiple-clicking, you may wish to lengthen this default value because the timeout applies to the composed multi-click event as well as the individual clicks.
In addition to the environment variable, this implementation provides a global variable with the same name. Portable applications should not rely upon the presence of ESCDELAY in either form, but setting the environment variable rather than the global variable does not create problems when compiling an application.
https://linux.die.net/man/3/ncurses
I submitted the pr https://github.com/gui-cs/Terminal.Gui/pull/1970 which I think fixes the ESC delay issue. I also think that the title of this issue isn't really an issue. What happen when the OCGV exits on a arrow key press is because there was a pending ESC key pressed to be processed and pressing the arrow key will awake the ESC, processing it first causing the app exit. So, the main problem here is the ESC delay issue on the CursesDriver which affect Linux and Mac OS.
@BDisp If you happen to have a build of the module with your changes happy to test and see if it does indeed fix this issue.
@BDisp If you happen to have a build of the module with your changes happy to test and see if it does indeed fix this issue.
I only have this branch https://github.com/BDisp/GraphicalTools/tree/solution-with-gui-project, where I added the Terminal.Gui project with the "cursesdriver-esc-delay-fix" branch, instead of the nuget package. You must have the clone of the Terminal.Gui with the pr https://github.com/gui-cs/Terminal.Gui/pull/1970 and build.
Yep did that and can confirm this fixes it
This issue is fixed in Terminal.Gui v1.8+. PR #184 will close it.