Guaranteed localization / Russification of the Windows console

Introduction

Console applications are still the most popular type of applications, most developers hone their architecture and business logic in the console. At the same time, they often face the problem of localization - the Russian text, which is quite adequately reflected in the source file, when displayed on the console takes the form of the so-called. "krakozyabr".





In general, localizing the Windows console with the appropriate language pack is not difficult. Nevertheless, a complete and unambiguous solution to this problem, in essence, has not yet been found. The reason for this mainly lies in the very nature of the console, which, being a system component implemented by the static class System.Console, exposes its methods to the application through system shell programs such as the command line or command processor (cmd.exe), PowerShell, Terminal and others.

In fact, the console is under dual control - applications and shells, which is a potentially conflict situation, primarily in terms of the use of encodings.





This material does not offer a strict algorithm of actions, but is aimed at describing the key problems that the developer of a localized console application inevitably encounters, as well as some possible ways to resolve them. It is assumed that this will allow the developer to form a strategy for working with a localized console and effectively implement existing technical capabilities, most of which are well described and are omitted here.





Types of consoles

In general, the console functions are as follows:





  • management of the operating system and the system environment of applications based on the use of standard system input-output devices (screen and keyboard), using the commands of the operating system and / or the console itself;





  • - , -.





Windows - (CMD). PowerShell (PS), Windows PowerShell (WPS) Terminal. Windows Windows Power Shell 5, - 7-, (, 6-) - . Terminal - , PowerShell .





Visual Studio (CMD-D).





, Windows, " " . , - DOS (CP437, CP866) Windows Unicode.





: / (habr.com)





Windows CP1251 (Windows-1251, ANSI, Windows-Cyr), 8- CP65001 (UTF-8, Unicode Transformation Format), , . , , Windows DOS - CP437 (DOSLatinUS, OEM) CP866 (AltDOS, OEM).





1. ( , .) UTF-8. , .





2. , Notepad++. Visual Studio , VS.





, " ", 1 2, :





- CMD, PS WPS. CHCP, Echo c (. 1), , UTF-8 (CP65001): , , , .





:





  • > Echo ffffff //





  • PS> Echo ffffff // PowerShell





  • PS> Echo ffffff ?????? // Windows PowerShell





:





using System;
using ova.common.logging.LogConsole;
using Microsoft.Extensions.Logging;
using ova.common.logging.LogConsole.Colors;

namespace LoggingConsole.Test
{
    partial class Program
    {
        static void Main2(string[] args)
        {
            ColorLevels.ColorsDictionaryCreate();
            Console.WriteLine("Hello World! , !");     //     
            LogConsole.Write("   ", LogLevel.Information);
            Console.WriteLine($"8. Active codepage: input {Console.InputEncoding.CodePage}, output {Console.OutputEncoding.CodePage}");
            Console.ReadKey();
        } 
    }
}
      
      



, : WPS .





Tab.  1. The result of the console command Echo ffffff ffffff
. 1. Echo ffffff

50% , .2.





Tab.  2. Result of running the LoggingConsole.Test application
. 2. LoggingConsole.Test

o 3. PowerShell . , ...





Windows DOS. CP437, CP866. cmd.exe 866, 437, .





4. CHCP - 866, 1251, 65001.





5. . : \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor Autorun : chcp < >. : Windows UTF-8 (qastack.ru), : Change default code page of Windows console to UTF-8.





Visual Studio

Visual Studio , Windows PowerShell . , , . - Windows, , , .





Visual Studio , Visual Studio , , , . , Windows , CHCP, . , , , 437 866.





6. , .





- ? - ".exe" , . , , , - - ,





Visual Studio

- , , , .





, - . Microsoft : "Programs that you start after you assign a new code page use the new code page. However, programs (except Cmd.exe) that you started before assigning the new code page will continue to use the original code page". , , , . - ?





! - , - -.





, . Write , , , , , . , .





F:\LoggingConsole.Test\bin\Release\net5.0>chcp
Active code page: 1251

F:\LoggingConsole.Test\bin\Release\net5.0>loggingconsole.test
Codepages: current 1251:1251, setted 437:437, ΓΓεΣΦ∞ 5 ±Φ∞ΓεδεΓ ∩ε-≡≤±±ΩΦ: Θ÷≤Ωσ=Θ÷≤Ωσ
Codepages: current 437:437, setted 65001:65001,  5  -: =
Codepages: current 65001:65001, setted 1252:1252, ââîäèì 5 ñèìâîëîâ ïî-ðóññêè: éöóêå=éöóêå
Codepages: current 1252:1252, setted 1251:1251,  5  -: =
Codepages: current 1251:1251, setted 866:866,  5  -є: Ўє=Ўє
Codepages: current 866:866, setted 1251:1251,  5  -: =
Codepages: current 1251:1251, setted 1252:1252, ââîäèì 5 ñèìâîëîâ ïî-ðóññêè: éöóêå=éöóêå

F:\LoggingConsole.Test\bin\Release\net5.0>chcp
Active code page: 1252
      
      



  • 1251 ( 2);





  • (current, setted);





  • 1252 ( 11, setted);





  • ( 14 - Active codepage 1252);





  • (setted 1251:1251) ( 8 10).





using System;
using System.Runtime.InteropServices;

namespace LoggingConsole.Test
{
    partial class Program
    {
        [DllImport("kernel32.dll")] static extern uint GetConsoleCP();
        [DllImport("kernel32.dll")] static extern bool SetConsoleCP(uint pagenum);
        [DllImport("kernel32.dll")] static extern uint GetConsoleOutputCP();
        [DllImport("kernel32.dll")] static extern bool SetConsoleOutputCP(uint pagenum);
        
        static void Main(string[] args)
        {
            Write(437);
            Write(65001);
            Write(1252);
            Write(1251);
            Write(866);
            Write(1251);
            Write(1252);
         }

        static internal void Write(uint WantedIn, uint WantedOut)
        {
            uint CurrentIn = GetConsoleCP();
            uint CurrentOut = GetConsoleOutputCP();
            Console.Write($"current {CurrentIn}:{CurrentOut} -  , "); /*wanted {WantedIn}:{WantedOut},*/
            SetConsoleCP(WantedIn);
            SetConsoleOutputCP(WantedOut);
            Console.Write($"setted {GetConsoleCP()}:{GetConsoleOutputCP()} -  , ");
            Console.Write($" 3  -: ");
            string str = "" + Console.ReadKey().KeyChar.ToString();
            str += Console.ReadKey().KeyChar.ToString();
            str += Console.ReadKey().KeyChar.ToString();
            Console.WriteLine($"={str}");
        }
      
        static internal void Write(uint ChangeTo)
        {
            Write(ChangeTo, ChangeTo);
        }
    }
}

      
      



- . .Net , WinAPI: SetConsoleCP(uint numcp) SetConsoleOutputCP(uint numcp), numcp - . : Console Functions - Windows Console | Microsoft Docs. WInAPI .





7. ! SetConsoleCP - .





  1. PowerShell ( ), Windows PowerShell;





  2. Set the default console code page to CP65001 (utf-8 Unicode) or CP1251 (Windows-1251-Cyr), see tip 5 ;





  3. Develop applications in utf-8 Unicode encoding;





  4. Control the encoding of source code files, text data files, for example using Notepad ++;





  5. Implement programmatic management of application localization in the console, example below under the cut:





An example of programmatically setting the code page and localizing the application in the console
using System;
using System.Runtime.InteropServices;

namespace LoggingConsole.Test
{
    partial class Program
    {
      	static void Main(string[] args)
        {
          	[DllImport("kernel32.dll")] static extern bool SetConsoleCP(uint pagenum);
        		[DllImport("kernel32.dll")] static extern bool SetConsoleOutputCP(uint pagenum);
            SetConsoleCP(65001);        //   utf-8 (Unicode)   
            SetConsoleOutputCP(65001);  //   utf-8 (Unicode)   
 
            Console.WriteLine($"Hello, World!");
        }
    }
}

      
      






All Articles