Cannot set output codepage
See original GitHub issueSteps to reproduce
Running chcp <codepage>
, setting [Console]::OutputEncoding
, or using PInvoke to call SetConsoleOutputCP should be setting the console output codepage. In Windows PowerShell this works but in PowerShell nothing is changed.
Add-Type -TypeDefinition @'
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
namespace RawConsole
{
public class NativeMethods
{
[DllImport("Kernel32.dll")]
public static extern uint GetConsoleCP();
[DllImport("Kernel32.dll")]
public static extern uint GetConsoleOutputCP();
[DllImport("Kernel32.dll")]
public static extern bool SetConsoleCP(
uint wCodePageID);
[DllImport("Kernel32.dll")]
public static extern bool SetConsoleOutputCP(
uint wCodePageID);
}
}
'@
# Take note of the original value
[RawConsole.Nativemethods]::GetConsoleOutputCP()
# Set using one of these 3 options, the value can be anything just something that isn't currently set
[RawConsole.Nativemethods]::SetConsoleOutputCP(1257)
chcp 1257
# On 2nd testing this does actually work
# [Console]::OutputEncoding = [Text.Encoding]::GetEncoding(1257)
# This should be updated with our new value
[RawConsole.Nativemethods]::GetConsoleOutputCP()
Note: You cannot use [Console]::OutputEncoding
to get the value for this test as it caches the value on the first call. This is why I’m using the PInvoke call to ensure there isn’t any caching shenanigans going on in the .NET layer.
Expected behavior
GetConsoleOutputCP()
should output 1257.
Actual behavior
GetConsoleOutputCP()
outputs the original value. This value is whatever the console output codepage was set to when pwsh.exe
was started.
Environment data
Name Value
---- -----
PSVersion 7.1.0
PSEdition Core
GitCommitId 7.1.0
OS Microsoft Windows 10.0.17763
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Using conhost and not Windows Terminal here. This also only affects PowerShell and not Windows PowerShell.
Other notes
Calling SetConsoleCP()
and GetConsoleCP()
works just fine it’s just the output codepage that doesn’t seem to have any affect. The Win32 function returns $true
which indicates nothing went wrong. I’m honestly unsure whether this is a conhost problem, .NET issue, or PowerShell problem. Just trying here first.
I’ve had a brief look at the OpenConsole code in the terminal repo. Ultimately SetConsoleOutputCP
calls DoSrvSetConsoleOutputCodePage and there’s nothing in there that jumps out to me to explain this behaviour. Of course I’m not actually using the OpenConsole.exe conhost but the one builtin to Windows and I’m 100% assuming the code is the same or at least not dramatically different. In any case it also doesn’t explain why Windows PowerShell works but PowerShell does not.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:15 (6 by maintainers)
Top GitHub Comments
Thanks to @SeeminglyScience (once again!) the issue comes down to
PSReadLine
resetting the console codepage after every statement (maybe command I’m not 100% sure). So by setting it throughchcp
or PInvoke it is actually being sent to conhost PSReadLine is just setting it back afterwards before I go to check the value.@SteveL-MSFT I can raise this issue in the PSReadLine repository but I assume it’s expected behaviour and you are just expected to use
[Console]::OutputEncoding
to set this value going forward so will hold off unless you want me to open it.Looking at git blame, it seems https://github.com/PowerShell/PSReadLine/commit/c3868e125069d87adbc5ee8f0274762a99510957 to address an issue with CJK chars coming from native commands