Гарантированная локализация/русификация консоли Windows

Введение

Консольные приложения до сих пор остаются наиболее востребованным видом приложений, большинство разработчиков оттачивают архитектуру и бизнес-логику именно в консоли. При этом они нередко сталкиваются с проблемой локализации - русский текст, который вполне адекватно отражается в исходном файле, при выводе на консоль приобретает вид т.н. "кракозябр".

В целом, локализация консоли Windows при наличии соответствующего языкового пакета не представляется сложной. Тем не менее, полное и однозначное решение этой проблемы, в сущности, до сих пор не найдено. Причина этого, главным образом, кроется в самой природе консоли, которая, являясь компонентом системы, реализованным статическим классом System.Console, предоставляет свои методы приложению через системные программы-оболочки, такие как командная строка или командный процессор (cmd.exe), PowerShell, Terminal и другие.
По сути, консоль находится под двойным управлением - приложения и оболочки, что является потенциально конфликтной ситуацией, в первую очередь в части использования кодировок.

Данный материал не предлагает строгий алгоритм действий, а направлен на описание узловых проблем, с которыми неизбежно сталкивается разработчик локализованного консольного приложения, а также некоторые возможные пути их разрешения. Предполагается, что это позволит разработчику сформировать стратегию работы с локализованной консолью и эффективно реализовать существующие технические возможности, большая часть которых хорошо описана и здесь опущена.

Виды консолей

В общем случае функции консоли таковы:

  • управление операционной системой и системным окружением приложений на основе применения стандартных системных устройств ввода-вывода (экран и клавиатура), использования команд операционной системы и/или собственно консоли;

  • запуск приложений и обеспечение их доступа к стандартным потокам ввода-вывода системы, также с помощью стандартных системных устройств ввода-вывода.

Основная консоль 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 неверно отображена русскоязычная часть команды во всех кодировках.

Табл. 1. Результат выполнения команды консоли Echo ffffff фффффф
Табл. 1. Результат выполнения команды консоли Echo ffffff фффффф

Вывод тестового приложения локализован лишь в 50% испытаний, как показано в табл.2.

Табл. 2. Результат запуска приложения LoggingConsole.Test
Табл. 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. Установить в качестве кодовую страницу консоли по умолчанию CP65001 (utf-8 Unicode) или CP1251 (Windows-1251-Cyr), см. совет 5;

  3. Разработку приложений выполнять в кодировке utf-8 Unicode;

  4. Контролировать кодировку файлов исходных кодов, текстовых файлов данных, например с помощью Notepad++;

  5. Реализовать программное управление локализацией приложения в консоли, пример ниже под катом:

Пример программной установки кодовой страницы и локализации приложения в консоли
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!");
        }
    }
}
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 82

    +7
    Удалить приложение PowerShell, заменив его Windows PowerShell;

    Что такое PowerShell, и чем он отличается от Windows PowerShell?

      0
      Допустил неопределеннось, виноват.
      PowerShell — новая мажорная версия (в моем случае 7-ка, 7.1.2), на которую предлагает перейти Windows PowerShell, устанавливаемая по умолчанию (у меня 5.1).
      PowerShell — кроссплатформенная (кроссплатформенность, вероятно, начинается с 6-ки). Но вот функциональность пока не очень. Собственно, корректнее будет не «удалить», а «не устанавливать PowerShell». Спасибо за замечание, поправлю.
        0

        Вы про PowerShell Core?

          0
          Скорее нет, чем да.
          Я вот про что:
          PS C:\Users\ova45> $PSversiontable
          Name Value
          — — PSVersion 7.1.2
          PSEdition Core
          GitCommitId 7.1.2
          OS Microsoft Windows 10.0.19041
          Platform Win32NT
          PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
          PSRemotingProtocolVersion 2.3
          SerializationVersion 1.1.0.1
          WSManStackVersion 3.0

          Это уже кроссплатформенная, а не дефолтная
            –1
            Скорее нет, чем да.

            А вот это что?


            PSEdition Core
              0
              А… ок. Значит про нее.
                0

                PS Core поддерживает Unicode, по крайней мере, по всей документации. Я не могу сейчас развернуть экземпляр и проверить, но подозреваю, что у вас в тестах где-то ошибка.


                Вы, например, на чистой системе без настроек и без CHCP пробовали?

                  0
                  Не, я не сомневаюсь в поддержке Юникода со стороны PS Core. Иначе и быть не может.
                  Думаю, проблема в другом, и суть ее вы уловили — «на чистой системе без настроек и без CHCP». PS Core как-то по-другому интерпретирует команды Windows. Конкретно — СHCP.
                    0
                    Не, я не сомневаюсь в поддержке Юникода со стороны PS Core. Иначе и быть не может.

                    Тогда зачем рекомендация "Про PowerShell забываем раз и навсегда."?

                      0
                      Не навсегда, а до следующей мажорной версии.
                        –1
                        Навсегда — это эксцесс исполнителя.
                          –1

                          Все равно зачем?

                            0
                            Вот смотрите. Вы мне не ответили на неявно поставленный вопрос — как с помощью CHCP изменить кодовую страницу вывода. Моя версия насчет формата с двумя страницами тоже не подтвердилась. А значит, по моему мнению, CHCP в данной версии работает некорректно.
                              –1
                              Вы мне не ответили на неявно поставленный вопрос — как с помощью CHCP изменить кодовую страницу вывода.

                              Не знаю.


                              А значит, по моему мнению, CHCP в данной версии работает некорректно.

                              Ну если ваша задача — это CHCP вызвать, то да, вам не подойдет.

                                0
                                С чего бы это? Моя задача, конкретно здесь и конкретно на первом этапе, была предельно проста — показать как установить дефолтную кодовую страницу в реестре. Она устанавливается с помощью команды CHCP. CHCP в PS Core работает некорректно. Возможно, в PS Core есть масса других полезных функций. Да та же кроссплатформенность.
                                Но тема поста — не PS Core.
                                  0
                                  Моя задача, конкретно здесь и конкретно на первом этапе, была предельно проста — показать как установить дефолтную кодовую страницу в реестре.

                                  А я-то думал, что у вас задача — чтобы текст из программы корректно выводился.

                                  0
                                  Добавлю. Если привычная функция, любая, в новой версии начинает вести себя некорректно, значительно снижая свою функциональность, имхо, это вполне достаточное основание полагать, что новая версия не доработана.
                                    –1

                                    … или что эта функция, вообще-то, не является частью новой версии, и поэтому вы можете ждать своей "доработки" бесконечно.

                                      0
                                      вообще-то если «эта функция не является частью новой версии», то она не явялется частью новой версии. Неожиданно, правда?
                                      Другое дело, что часто «эта функция» сохраняется для совместимости со старой версией, а к ней добавляется аналогичная новая с расширенным фнкционалом. Примерно так же, как это и произошло с PS и PS Core.
                          0
                          Вот теперь проблема стала понятнее, но от этого не перестала быть проблемой. В отличие от предыдущих версий, PS Core по команде CHCP устанавливает не обе кодовых страницы, а только страницу ввода.
                          Возможно, у нее существует формат (не проверял) типа
                          CHCP inputpagenum outputpagenum
            +12
            Изменить кодовую страницу консоли Windows по умолчанию на UTF-8 (qastack.ru)

            Вот корректная ссылка. Не надо пользоваться мусорными промптопереводилками.
            superuser.com/questions/269818/change-default-code-page-of-windows-console-to-utf-8
              +1
              Спасибо за ссылку. Честно говоря, я не придал ей большого значения, потому что те, кого подробности действительно интересуют, по этой же ссылке (а она все-таки, как и пост, русскоязычная), или с ее помощью уйдут на оригинал. Ну а кроме того, как мне кажется, в контексте данного поста подробности не столь важны, поскольку основная идея — русифицируйте консоль в коде, и будет вам счастье.
              Однако в общем смысле вы, конечно, правы. Ваше замечание учту.
              +1
              Для смены кодировки есть такие свойства консоли, можно не импортировать функции:
              Console.OutputEncoding = System.Text.Encoding.UTF8;
              Console.ItputEncoding = System.Text.Encoding.UTF8;
                0
                Верно, спасибо за замечание. По существу об этом нужно было упомянуть, но тогда нужно упомянуть и о том, что эти функции ограничены кодировками Юникода, плюс дефолтная кодировка Net, плюс 7-битная ASCII. На этом все. Более полезны были бы свойства типа Console.OutputEncoding.CodePage, но к сожалению, они ReadOnly.
                С другой стороны, в контексте данного поста, упомянутых вами функций вполне достаточно — мы же стремимся к Юникоду, верно? Так что спасибо, поставил бы плюсик за коммент, но карма не позволяет.
                  +3
                  Можно указать любую кодировку:
                  Console.OutputEncoding = System.Text.Encoding.GetEncoding(866);
                    0
                    Ок. Существенное замечание.
                +1
                оболочки PowerShell (PS), Windows PowerShell (WPS) и Terminal

                «Windows Terminal» — представитель отдельного класса приложений
                Windows Terminal, ConEmu, Hyper — это эмуляторы терминалов или консолей
                PowerShell, bash, cmd — это оболочки, shell, cli (command-line interpreters)

                What's the difference between a console, a terminal, and a shell?

                  0
                  Ну знаете, это все споры о терминах. По существу все вышеперечисленное — это оболочки или обертки. Интерпретаторы команд Windows API. Microsoft называет это все командным процессором. Из чего это следует? А вот из чего — параметры раздела реестра \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor влияют на все перечисленные оболочки. Почит все параметры на почти все оболочки.
                    –1
                    Microsoft называет это все командным процессором

                    Можно, пожалуйста, ссылку на то место, где Microsoft называет Windows Terminal командным процессором?

                      –1
                      Предлагаю о терминах не спорить. Если хотите, можете называть Terminal оболочкой над оболочками.
                      Переведено с английского языка.-Терминал Windows — это интерфейс командной строки с несколькими вкладками, который Microsoft разработала для Windows 10 в качестве замены консоли Windows. Он может запускать любое приложение командной строки, включая все эмуляторы терминала Windows, на отдельной вкладке. Википедия (Английский язык)

                      Все «эмуляторы», «консоли» и пр. работают под управлением вот этой строки реестра Windows: \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor.

                      –1
                      Сайт, Интернет и браузер тогда тоже, получается, одно и то же.
                        0
                        Да бог с вами, с чего бы это? Вы бы еще статью об Интернете из бумажного Коммерсанта добавили в этот список для полного счастья.
                    0
                    Стратегия локализации приложения в консоли

                    Вообще же, я пребывал в уверенности, что "гарантированная локализация" — это когда вы отдаете программу пользователю, а оно у него работает так, как вам бы хотелось. И если пользователю для этого надо выкинуть используемый им шелл и поставить другой — это как-то очень странно.

                      0
                      Верно. Поэтому пост нацелен на программную локализацию консоли, а выкинуть/добавить шелл — это как бы предварительные, но не очень удачные действия. Жаль, что акцент не удался.
                        0
                        Поэтому пост нацелен на программную локализацию консоли, а выкинуть/добавить шелл — это как бы предварительные, но не очень удачные действия.

                        Это вредные действия.

                          0
                          Я бы не был столь категоричен. Возможно, учитывая общий контекст, излишние действия. Однако не следует забывать, что можно элементарно забыть о добавлении установки кодовой страницы в код. А в результате этих вредных действий, с большой долей вероятности вы таки получите локализованную консоль.
                            0

                            Ровно наоборот. В результате этих действий я, как разработчик, получу локализованный вывод, не заметив, что среднестатистический пользователь его не получит. Это и есть вред.

                              0
                              Я вашу логику уловил сразу, пояснения излишни. Я исхожу из другого — эта локализация для разработчика. Ровно потому, что среднестатистический пользователь — нелокализованный пользователь. Напоминаю, я говорю преимущественно о консоли разработчика, который вполне может ограничиться дефолтной локализацией своей консоли, и ограничить консольный вывод отладочной информацией. А логирование приложения выполнять как-то иначе, например исключительно на английском. Или не выполнять вообще.
                              Коротко говоря, дефолтная локализация консоли разработчика программной локализации не повредит, а помочь иногда может.
                              Ваше мнение понятно, право на существование имеет. Выбор подхода за разработчиком, наша мини-полемика ему в этом поможет. И давайте вот именно по этому вопросу на этом остановимся.
                                –1
                                Я исхожу из другого — эта локализация для разработчика.

                                А для разработчика можно вообще всей этой странной активностью не заниматься, если честно. В консоли все равно отлаживаться неудобно, а за пределами консоли (хотя у меня и в пределах не было особых проблем) в .net с Unicode просто все работает.

                                  0
                                  да не, мне консоль удобна. Отсюда кстати вся это «странная активность». Нужда заставила.
                      0
                      Исторически кодовой страницей Windows является CP1251 (Windows-1251, ANSI, Windows-Cyr)
                      ANSI — это целая пачка национальных кодовых страниц
                      CP1251 — это конкретно российская кодовая страница, одна из набора ANSI

                      уверенно вытесняемая 8-битной кодировкой Юникода CP65001 (UTF-8
                      Windows работает в UTF-16:
                      For compatibility with 8-bit and 7-bit environments, Unicode can also be encoded as UTF-8 and UTF-7, respectively. While Unicode-enabled functions in Windows use UTF-16, it is also possible to work with data encoded in UTF-8 or UTF-7
                      New Windows applications should use UTF-16 as their internal data representation.


                      Совет 1. Выполнять разработку текстовых файлов (программных кодов, текстовых данных и др.) исключительно в кодировке UTF-8.
                      может лучше прислушаться к рекомендациям Microsoft?
                        +1
                        ANSI — это целая пачка национальных кодовых страниц
                        CP1251 — это конкретно российская кодовая страница, одна из набора ANSI


                        Верно, но мне кажется вполне очевидным, что речь идет о русифицированной Windows.

                        может лучше прислушаться к рекомендациям Microsoft?


                        А вот это спорно. Не в том смысле, что MS ошибается, а в том, что рекомендации MS конкретно в этом случае противоречивы. Но вотпрямщаз я не готов сравнивать кодировки Юникода. Это тема отдельного поста.

                        0
                        Актуальные версии командной строки cmd.exe способны локализовать приложения
                        «локализовать приложения» — это совсем про другое, это про перевод, национальные стандарты и т.п. Этим занимаются разработчики, а cmd.exe
                          0
                          Формально вы правы, но далее понятие уточняется: «На самом деле, правильнее говорить о локализации приложения в консоли — это важное уточнение».
                          Т.е. речь идет не о локализации приложения, а о локализации его отображения в консоли… бла-бла-бла. Коротко — локализация приложения в консоли. И да, даже в этом случае термин не корректен, поскольку речь может идти также и о национальном стандарте времени в консоли.
                          Но что делать? Не описывать же каждый раз объект и предмет двумя-тремя абзацами…
                          0
                          Консольные приложения до сих пор остаются наиболее востребованным видом приложений, большинство разработчиков оттачивают архитектуру и бизнес-логику именно в консоли.

                          Вот прямо большинство? И прямо оттачивают? И прямо бизнес-логику и архитектуру? :)

                            0
                            Оценочное суждение. Не только мое.
                            0

                            На самом деле, вы что-то делаете не так изначально.


                            PS> Echo ffffff ?????? // так выглядит та же команда в Windows PowerShell

                            Вот вам поведение PowerShell "из коробки":


                            (проверено на двух разных компьютерах, где ОС даже разные люди устанавливали)


                            Откуда у вас взялись знаки вопроса?

                              0
                              Не знаю, и вникать не хочу. Если вы заметили, я на этом внимание не акцентировал, и не предлагал убить дефолтную 5-ку. Полагаю, что это результат моих дефолтных установок. Пока мне не мешает, при необходимости поправлю. А в качестве иллюстрации правильности программной локализации как раз даже наоборот — помогает.
                              Что касается «делаете неправильно» попробуйте выдать chcp 1251, например, а затем chcp 65001, тоже например. В разных консолях. А после каждой chcp запустить код типа:
                              Writeline(GetConsoleInputCP());
                              Writeline(GetConsoleOutputCP());

                              Результат вас удивит. В 5-ке вы получите
                              1251
                              1251
                              65001
                              65001
                              а в 7-ке:
                              1251
                              437 (скорее всего, потому что 437 — дефолтная, ну или другую текущую CP)
                              65001
                              437 (или опять же другую текущую)

                              Вот и вся проблема. Две абсолютно одинаковых команды не должны по-разному работать в разных версиях одной и той же программы.
                                0
                                Не знаю, и вникать не хочу.

                                Печально.

                                  0
                                  Отчего так?
                                    –1

                                    Оттого, что вы не хотите разбираться в том, о чем, собственно, ваш пост.

                                      +1
                                      Мой пост не о PS Core. И не о PS. Если вы перечитаете первые пару абзацев, то возможно уясните, что у меня нет задачи дать строгий алгоритм, а указать на возможные проблемы, и возможные пути их разрешения. Что я и сделал.
                                      Повторюсь. Косяк в дефолтной консоли — он мой, и не является, не должен являться проблемой остальных. А уж когда я с ним разберусь… это, в принципе, никого не касается.
                                  0
                                  Отдельно дополню. Знаки вопроса в 5-ке при вводе — мой косяк, мне кажется я это дал понять в тексте, и он несущественнен для сути поста. Он только мой. А вот косяки 7-ки, это косяки консоли. Они общие, поэтому я на них и акцентировался.
                                    0
                                    Две абсолютно одинаковых команды не должны по-разному работать в разных версиях одной и той же программы.

                                    Почему вдруг? Вы никогда не слышали про breaking changes?

                                      0
                                      breaking changes абсолютно никакого отношения к рассмтриваемой ситуации не имеет.
                                      Ну или если упереться в формальный термин, то в нашем случае breaking changes — это голимый косяк. Это примерно как однопоточное приложение признать потоконебезопасным.
                                        0
                                        breaking changes абсолютно никакого отношения к рассмтриваемой ситуации не имеет.

                                        Почему? То, что случилось, это оно и есть.

                                          0
                                          Нет, не оно. «Оно» относится к ситуации, когда компонент рассчитан на взаимодействие с неким классом других компонентов. Тогда завляются требования, исполнение которых гарантирует корректное взаимодействие. Если таковые не исполняются, взаимодействие компонентов не гарантируется. Но возможно. Пожалуй, наиболее яркий пример — Windows 10. В которую и были внесены breaking changes, о чем было широко заявлено. Большиство простеньких приложений прокатывало, но более сложные, использующие функционал ОС по максимуму, судорожно начали лепить костыли. Ну и MS тоже в этом поучаствовала.
                                          В нашем случае однм компонент взаимодействует с другим. ОС с консолью. Поэтому все костыли должны быть слеплены до релиза.
                                            0
                                            «Оно» относится к ситуации, когда компонент рассчитан на взаимодействие с неким классом других компонентов

                                            Консольная оболочка — тоже такой компонент.

                                              0
                                              Да, я об этом и сказал. Но здесь речь идет о взаимодействие компонента не с классом компонентов, а одного с одним. ОС и консоль. Поэтому все брикинги должны быть убраны. Это невозможно, или затруднительно для класса компонентов (например для всех приложений под Windows при переходе на 10-ку), но обязательно для случая один на один.
                                              Ну какой тут брикинг ченджс? Ребята, мы сделали новую прогу, но пара функций точно не работает, а еще процентов 50 мы точно не знаем. Удачного кодинга или юзинга!
                                              Вы че, смеетесь? Или троллите меня? Я человек доверчивый, меня троллить легко — а вам ни славы, ни удовольствия.
                                                0
                                                Но здесь речь идет о взаимодействие компонента не с классом компонентов, а одного с одним.

                                                Нет, о реакции компонента (PS) на команду.


                                                Поэтому все брикинги должны быть убраны.

                                                Да никому никто ничего не должен. С чего вы взяли? Вы так говорите, как будто вас кто-то заставляет на Core апгрейдиться. Вот я знаю, что у меня под ней не заведется несколько скриптов именно из-за breaking changes — и сижу на пятерке.

                                                  0
                                                  Да и вы не должны мне писать, однако пишете. И я не должен, однако пишу. Давайте-ка понизим накал — время жалко. Поэтому к делу.
                                                  Ваш пример опять неудачен, хотя бы потому, что не раскрыт. Попробую сделать это за вас. Ваши скрипты не заводятся по одной из трех причин:
                                                  1. Удалена команда. Случай редкий, поскольку снижена функциональность без объявления войны. Типичный breaking changes. Объявление обязательно, поскольку необъявленные брикинги чреваты судебными исками, и не всегда «As is» прокатывает.
                                                  2. Функционал команды изменен. Случай нередкий. Обычно в этом случае меняется и формат команды, включая имя. Просто для того, чтобы сохранить старую команду для обеспечения совместимости.
                                                  3. Функционал добавлен к другой команде. См. п.2
                                                  4. Функционал изменен без смены имени и формата. По каким-то неведомым причинам. Нетипично, но тогда это breaking changes и требуется объявление потому что… см. п.1. Где удобнее всего сделать? При вызове команды.
                                                  5. см. п.4 но без объявления — наш случай. Это косяк, потому что… см. п.1
                                                    0
                                                    Ваши скрипты не заводятся по одной из трех причин

                                                    И какая мне разница-то? Мне важно, что они не заводятся, и их надо чинить.


                                                    поскольку необъявленные брикинги чреваты судебными исками

                                                    Серьезно? На основании чего?

                                                      0
                                                      Серьезно. На основании предоставления продукта не соответствующего техническому описанию.
                                                        0

                                                        Процитируйте, пожалуйста, пункт binding agreement, в котором разработчик и/или издатель PowerShell Core обязуются соответствовать какому бы то ни было техническому описанию.


                                                        Процитирую, на всякий случай, ту лицензию, которую удалось найти мне:


                                                        PowerShell Core is released under the MIT license. Under this license, and without a paid support agreement, users are limited to community support. With community support, Microsoft makes no guarantees of responsiveness or fixes.

                                                        (https://docs.microsoft.com/en-us/powershell/scripting/powershell-support-lifecycle?view=powershell-7.1#notes-on-licensing)


                                                        THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

                                                        (https://github.com/PowerShell/PowerShell/blob/master/LICENSE.txt)


                                                        Судебный иск? Я бы почитал обоснование-то, да.

                                                            +1

                                                            Неа.


                                                            У вас нет на руках ни договора подряда, ни договора возмездного оказания услуг. Вы вообще не являетесь заказчиком в этих отношениях.


                                                            Единственный договор, на который можно сослаться в суде — это лицензионное соглашение выше. Оно имеет все признаки открытой лицензии и как следствие регулируется статьей 1286.1 ГК РФ.


                                                            Там нет ничего о "несоответствии техническому описанию" и вообще нет никаких обязанностей лицензиара.

                                                              0
                                                              еще раз.
                                                              п. 1.2
                                                                0

                                                                Нет. У вас нет никакого заказа. Собственно, даже в статье об этом написано:


                                                                Вместе с тем, указанные варианты представляются не совсем применимыми к случаям покупки готового ПО.
                                                                  0
                                                                  В третий раз. п. 1.2.
                                                                  1.2. К данной ситуации имеется и второй подход, который гораздо менее распространен, но и его стоит учитывать. Согласно данному подходу к правоотношениям сторон по лицензионному договору (!!!) по аналогии могут быть применены положения глав 37-39 ГК РФ об оказании услуг и подряде, что позволяет правообладателю ссылаться на недостатки результата работ.

                                                                  дальше сами. Глазками.
                                                                    0
                                                                    К данной ситуации имеется и второй подход

                                                                    К какой конкретно "данной ситуации", учитывая, что в конце статьи явно написано:


                                                                    Вместе с тем, указанные варианты представляются не совсем применимыми к случаям покупки готового ПО.

                                                                    Напомню так же, что чуть ниже процитированного вами текста идет ссылка на п. 6 ст. 13 АПК РФ (только он дает возможность применения глав 37-39 "по аналогии"), который звучит так:


                                                                    В случаях, если спорные отношения прямо не урегулированы федеральным законом и другими нормативными правовыми актами или соглашением сторон и отсутствует применимый к ним обычай делового оборота

                                                                    Однако в случае с PowerShell Core отношения явно урегулированы статьей 1286.1 ГК РФ, так что это все вылетает в трубу.


                                                                    Прямо скажем, статья 1286.1 введена в 2014 году, а практика, на которую вы ссылаетесь — 2012, так что оно еще и неактуально.

                                                                      –1
                                                                      А давайте вы лучше с судом поспорите- там ведь ссылки на решения есть. А если хотите актуальности — ищите ее сами.
                                                                        0

                                                                        А мне-то зачем с судом спорить? Я не утверждал, что за что-то можно судебный иск подать. И ответчиком тоже выступать по этому делу не буду.

                                                                          –2
                                                                          Так вы с ним и спорите, тока через меня. А я вам предлагаю напрямую. Вот там есть ссылки на решения — вы их и оспаривайте. Напрямую.
                                                                            0

                                                                            Неа, я с не с ними спорю. Я спорю с вами. Вы сделали утверждение, вам его и доказывать.

                                                                              –2
                                                                              ну я так и думал. Вы как Порос — я дерусь..., потому что дерусь…
                                                                              Удачи. Спарринга не будет.
                                                0
                                                А вот представьте — переход на Windows 10, и не одно приложение не работает. Ни одно! Как вы полагаете, было бы это breaking changes? Да ни фига, как бы эта винда не называлась — пусть даже «Windows XP чуть-чуть получше». Это была бы новая система. И к ней новые приложения. И никаких ченджей.
                                                  0
                                                  А вот представьте — переход на Windows 10, и не одно приложение не работает. Ни одно! Как вы полагаете, было бы это breaking changes?

                                                  Это называется "полная потеря обратной совместимости".

                                                    –1
                                                    Только не обратной, а просто совместимости. Обратная совместимость — когда новое приложение для новой ОС, работает под старой версией ОС.
                                                      0
                                                      Обратная совместимость — когда новое приложение для новой ОС, работает под старой версией ОС.

                                                      https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D1%82%D0%BD%D0%B0%D1%8F_%D1%81%D0%BE%D0%B2%D0%BC%D0%B5%D1%81%D1%82%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D1%8C


                                                      наличие в новой версии компьютерной программы или компьютерного оборудования интерфейса, присутствующего в старой версии, в результате чего другие программы (или человек) могут продолжать работать с новой версией без значительной переделки (или переучивания).

                                                      Нет.

                                                        –2
                                                        Что нет?
                                                        Вот выдержка с вашей же ссылки:
                                                        Обратная совместимость в программном обеспечении
                                                        Обратная совместимость применительно к программному обеспечению означает способность более поздних версий программы работать с файлами, созданными более ранней версией этой же программы или программы, реализующей те же алгоритмы, что и более ранняя версия. Так, например, в Microsoft Office присутствует поддержка целого ряда форматов, которые на данный момент почти не используются.

                                                        Сравните с моим:
                                                        Обратная совместимость — когда новое приложение для новой ОС, работает под старой версией ОС.

                                                        Перевожу, если сразу непонятно:
                                                        Новое приложение, для того чтобы работать под старой ОС, должно сохранять старые функции, отсутствующие в новой.
                                                        Так же, как новый MS Office сохраняет старые форматы.
                                                          0
                                                          Новое приложение, для того чтобы работать под старой ОС, должно сохранять старые функции, отсутствующие в новой.

                                                          Вы, я боюсь, немножко не понимаете взаимодействие ОС и приложения.


                                                          Но, честное слово, уже надоело.

                                                            –2
                                                            Вы не понимаете — это убойный аргумент. Контрольный выстрел.
                                                            Честно говоря, надоело уже давно. Так что, всего вам доброго.

                                  Only users with full accounts can post comments. Log in, please.