question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot set output codepage

See original GitHub issue

Steps 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:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:15 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
jborean93commented, Mar 4, 2021

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 through chcp 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.

1reaction
SteveL-MSFTcommented, Mar 5, 2021

Looking at git blame, it seems https://github.com/PowerShell/PSReadLine/commit/c3868e125069d87adbc5ee8f0274762a99510957 to address an issue with CJK chars coming from native commands

Read more comments on GitHub >

github_iconTop Results From Across the Web

Change Console Code Page in Windows C++
I'm trying to output UTF8 characters in the Windows command line. I can't seem to get the function, setConsoleOutputCP to work. I also...
Read more >
Change default code page of Windows console to UTF-8
To change the codepage for the console only, do the following: Start -> Run -> regedit; Go to [HKEY_LOCAL_MACHINE\Software\Microsoft\Command ...
Read more >
stdout.encoding not set when redirecting windows ...
msg154885 ‑ (view) Author: Redoute (Redoute) Date: 2012‑03‑04 09:42 msg154888 ‑ (view) Author: Martin v. Löwis (loewis) * Date: 2012‑03‑04 12:05 msg154892 ‑ (view) Author:...
Read more >
Incorrect shell output encoding
My problem lies in the encoding of the result of this operation; I can't display accented characters correctly. In the program, I can...
Read more >
Code Pages
A Code Page (also referred to as Character Set or Encoding) is a table of values where each character has been assigned a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found