2

Вот что я хочу сделать:

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

Что я наблюдал:

Chcp эффективен с внутренними командами и некоторыми внешними командами (последние)

Прежде всего стоит отметить, что CHCP работает по-разному под Win7 и Win 10.

Если следующий пакет запускается из командной строки cmd, вы можете заметить, что выходные данные команды правильно отображаются в консоли win10, тогда как консоль win7 плохо отображает символы из ASCII.

for /f "tokens=2 delims=:" %%G in ('chcp') do Set _cp_=%%G
chcp 1252
@echo test an internal command
dir
@echo test an external (recent) command: Robocopy
robocopy .\ .\ /L
@echo test an external (legacy) command: Xcopy
xcopy test.txt 2>&1
chcp %_cp_%
echo end of test.cmd batch 

Кстати, мне интересно узнать, что вызывает такую разницу, хотя на самом деле это не цель этого сообщения, и поскольку это легко исправить, добавив ps invoke «powershell [console]::outputencoding = [system.text.encoding]::getencoding(850)»в пакете после 1-й команды chcp.

Независимо от реальной проблемы возникает, когда пакетный вывод перенаправляется в файл: test.cmd> test.txt.

В этом случае результат будет одинаковым для любой ОС. Выходные данные внутренних команд и новых внешних команд (Robocopy, Bcdedit и т.д.) Должным образом кодируются 1252. Устаревшие команды (xcopy, chcp и т.д.) - нет (вывод в кодовой странице OEM). Короче говоря, на большинство команд не влияет CHCP или эквивалентное изменение [консоли] через powershell.

Различные предположения об этом беспорядке:

  1. Устаревший код команды основан на CRT, тогда как внутренние и последние внешние команды используют Win32 API. Это основано на последнем разделе, касающемся разработки консольного приложения от MSDN Globalization, шаг за шагом !

  2. Поскольку по крайней мере win10 то, что отображается в консоли (одинаковая кодировка для всех выходных данных команды) и сохраняет файл, отличается (выходная кодировка изменяется в зависимости от команды), потоки вывода / ввода могут обрабатываться по-разному в зависимости от типа дескрипторов, на которые они указывают. Консольные функции могут использоваться для отображения и функций файла ввода / вывода в случае перенаправления. Спекуляция на основе высокоуровневых консольных функций ввода и вывода !

  3. MS рекомендует код консольных приложений, заставляет OEM-кодировку выходного потока. Ссылка Проблемы консольного приложения Если в коде внешних команд применяется предложение MS, которое может объяснить, почему перенаправление их выходных потоков в файл всегда кодируется OEM_CP независимо от того, применяется ли кодовая страница консоли. Как ни странно, readfile и writefile не упоминаются среди функций, затронутых SetFileApisToOEM

Наконец, я не знаю, заключается ли разница между устаревшими и недавно введенными командами в том, что их код соответствует предложению MS и просто потому, что строковые литералы кодируются как OEM против ANSI.

Возможные решения / обходной путь

Если 3 правильно, их, безусловно, очень мало. Можно изменить значение ключа реестра HKLM\system\currentset\control\NLS\codepage OEMCP = 1252. Это небезопасно (не пытайтесь установить Unicode 65001, ваша система может отказаться от загрузки) и неудобно (необходима перезагрузка). Или, заполнив файл только OEM-кодированным содержимым и перекодировав файл с помощью сценария PS в конце пакета. Простой, но не очень элегантный, если к файлу нужно периодически обращаться и проверять.

Если 2 верно, может существовать функция, которая управляет кодированием файловых функций ввода-вывода readfile и writefile.

Если 1 верно, то должна быть возможность контролировать международные настройки или культуру текущего сеанса пользователя и, таким образом, контролировать кодовую страницу приложения CRT. Начиная с Win8, это возможно с помощью Powershell Configure International Settings в Windows. Приложения командной строки также могут выполнять такие вещи. Как бы то ни было, сложность здесь заключается в создании «культуры» с кодовой страницей OEM, установленной на 1252, так как ее нет в предопределенном наборе.

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

0