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

  1. Enable Russian keyboard layout on Windows (I use Alt-Shift to do that)
  2. Start PowerShell Core 7.0 (which includes PSReadLine 2.0)
  3. 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

Most upvoted comments

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.

Warning Normally, you should not download files from the internet and replace the vendor stuff with them, but in this case it’s the only quick solution I’ve found.

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 or Install-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:

  1. Start PSReadline (e.g. by starting PSReadline-net461 from sources).
  2. Enable Russian keyboard layout, and then press Ctrl-C or Ctrl-R one time (it won’t work).
  3. After that, you may change the current keyboard layout as many times as you want, Ctrl-hotkeys won’t work for you in this session. The session is absolutely broken.

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 press Ctrl-r with English keyboard layout enabled (and the input argument properly indicates Ctrl+r as being pressed). Most likely, there’re two different issues:

  1. Something in 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.
  2. It just doesn’t work as it should: it relies on the current keyboard layout for some reason, when the expected behavior would be to ignore it and always use the default one (at least, every single program I know behaves that way with the Russian+English keyboard layouts; there may be some exceptions from this rule, but I’m not aware of them yet).

I’ll try to investigate further.

Still annoying that it doesn’t work with Cyrillic

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.

Ok, 2.3.3+e8 is correct: it is the commit with my fix.

Could you please show the process tree of this pwsh process? Does it have Terminal as the parent process?

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

(Get-Module -Name PSReadLine).path

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

Isn’t this repository already a PSReadLine repo?

Oh, sorry.