PSReadLine: Ctrl-C doesn't work if PowerShell was started with Russian keyboard layout
Environment
PS version: 7.0.0
PSReadline version: 2.0.0
os: 10.0.18362.1 (WinBuild.160101.0800)
PS file version: 7.0.0.0
HostName: ConsoleHost
BufferWidth: 170
BufferHeight: 32766
Steps to reproduce
- Enable Russian keyboard layout on Windows (I use Alt-Shift to do that)
- Start PowerShell Core 7.0 (which includes PSReadLine 2.0)
- Press Ctrl-C in the shell
Expected behavior
Ctrl-C should terminate current command/input/whatever, it should work as Ctrl-C usually do.
Actual behavior
Russian letter “с” getting inserted into the command line, and no actual Ctrl-C behavior happens.
Ctrl-C is still broken even if I switch to the English keyboard layout (then English letter “c” gets inserted inctead of actual Ctrl-C behavior heppening).
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 12
- Comments: 47 (28 by maintainers)
Commits related to this issue
- Fix #1393: avoid dead key check for known unambiguous control characters — committed to ForNeVeR/PSReadLine by ForNeVeR 4 years ago
- Fix #1393: avoid dead key check for known unambiguous control characters — committed to ForNeVeR/PSReadLine by ForNeVeR 4 years ago
- (#1393) Windows keyboard layout: determine parent terminal process and get the layout from it — committed to ForNeVeR/PSReadLine by ForNeVeR 10 months ago
- Fix #1393: avoid dead key check for known unambiguous control characters — committed to ForNeVeR/PSReadLine by ForNeVeR 4 years ago
- (#1393) Windows keyboard layout: determine parent terminal process and get the layout from it — committed to ForNeVeR/PSReadLine by ForNeVeR 10 months ago
- Fix #1393: avoid dead key check for known unambiguous control characters — committed to ForNeVeR/PSReadLine by ForNeVeR 4 years ago
- (#1393) Windows keyboard layout: determine parent terminal process and get the layout from it — committed to ForNeVeR/PSReadLine by ForNeVeR 10 months ago
- Fix #1393: avoid dead key check for known unambiguous control characters — committed to ForNeVeR/PSReadLine by ForNeVeR 4 years ago
- (#1393) Windows keyboard layout: determine parent terminal process and get the layout from it — committed to ForNeVeR/PSReadLine by ForNeVeR 10 months ago
- (#1393) Address the PR feedback — committed to ForNeVeR/PSReadLine by ForNeVeR 8 months ago
- (#1393) Address the PR feedback — committed to ForNeVeR/PSReadLine by ForNeVeR 8 months ago
- (#1393) Windows keyboard layouts: introduce the process tree logic — committed to ForNeVeR/PSReadLine by ForNeVeR 8 months ago
- (#1393) Address the PR feedback — committed to ForNeVeR/PSReadLine by ForNeVeR 8 months ago
Yes, the bug still exists for Russian layout.
Alright, folks. I am very tired of this issue, so I’ve decided to publish a workaround.
C:\Program Files\PowerShell\7\Modules\PSReadLine\Microsoft.PowerShell.PSReadLine2.dll
with this file.I’ve tried packing it up properly with a different name, but haven’t been successful: it turns out that PowerShell really insists on loading the real PSReadline on startup, which breaks any of my workarounds with publishing the same module with alternate name.
If someone has experience with publishing/authoring PS modules, please take a look and help me to publish it properly, so
Get-Module
orInstall-Module
would work.The workaround I’ve decided to use is this commit. It should force the
ToUnicode
to use US English layout when consuming the hotkey presses (Dvorak folks, I’m sorry, and I’m ready to provide an option and/or an alternative build for you if required!)I also have a hypothesis (somewhat tricky to check unfortunately) that if we add a way to get the right version of the current keyboard layout in that code, then we can fix the issue somewhat (it won’t be perfect, but will stop sticking with the wrong layout it seen on the first key press).
Unfortunately, this is quite tricky to do: the normal
WM_INPUTLANGCHANGE
message only gets sent to the active window (and our background keyboard-processing thread is definitely not the active window and cannot own one), and so the only remaining way to do it is via some COM interop and ITfActiveLanguageProfileNotifySink. I haven’t tried that, but COM interop in modern .NET is a bit messy, so I’d also accept help on that. It’s hard to even try that to check if it will work.Conclusion
So, for now, enjoy the workaround (and I hope I’ll be able to publish updated versions of that package while pwsh gets updated), and maybe in the future I’ll experiment more on a better workaround that we can merge into the main repository.
I have to say I am a bit disappointed with how the PSReadline team has handled this issue and my pull request. But I still love and respect y’all folks for your great job, and hope we’ll be able to improve our communications in the future.
Folks, love y’all so much. Finally, we’ll have a significant improvement on this in the next release ❤️
The shortcuts are still expected to be defunct if you have a “wrong” keyboard layout enabled when you hit
Ctrl+C
, but it won’t stick with you until the end of PowerShell session: just change the layout to English, and it will start working again.It was verified in several terminal apps (including the Windows Terminal, of course), but there are cases when it is still broken (e.g. in the old console, or when you start Windows Terminal as a default terminal app, as opposed to explicitly clicking the Terminal icon).
I’d suggest to report new cases separately, and you may link them in this thread. I’ll try to take a look at new particular scenarios and improve them if possible.
But again: we expect that in majority of cases, the issue will be gone next release. I am so happy 🎉
Still broken on PowerShell 7.3.5 with PSReadLine 2.2.6, with other languages too.
wha have any solutions or workarounds?
Exact steps to reproduce:
PSReadline-net461
from sources).Also, I’ve been able to reproduce the issue both in PowerShell Core and in PowerShell 5.1.
I was able to determine that the culprit is likely
Microsoft.PowerShell.PSKeyInfo.KeyInfoAsString
: this method returns a string"Ctrl+к"
even when I pressCtrl-r
with English keyboard layout enabled (and the input argument properly indicatesCtrl+r
as being pressed). Most likely, there’re two different issues:PSKeyInfo
is static and wrongly so, so it remembers my (Russian) keyboard layout when I enter this method for the first time, and then reuses this layout even if I change it afterwards.I’ll try to investigate further.
Unfortunately, the current opinion is that such behavior would actually break the habits of some users (who use shortcuts in local keyboard layouts; such a thing exists!), and my early tries to fix it that way broke the PSReadline tests. So I’ve decided to have a more lightweight fix that only loads the current layout correctly before looking up the shortcut.
@ForNeVeR I will make sure get to it this week. I’ve also added a reviewer who has good experience in the Windows console area, and hopefully we can get his help too.
I found the reason. The PSReadLine module was installed in the user’s environment, although I did not specify the scope. I added your file there and everything worked as expected. Thank you! I would add to the instructions a definition of the path where the file should be copied
Eh, here I am, I reported this issue to Windows Terminal first because I couldn’t reproduce it outside of the Windows Terminal but yeah, this issue still present and is very annoying. https://github.com/microsoft/terminal/issues/14318
Oh, sorry.