Вот что я хочу сделать:
Перенаправление правильно вывода консольных приложений (я использую термин команду в остальной части сообщения) в файл с 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.
Различные предположения об этом беспорядке:
Устаревший код команды основан на CRT, тогда как внутренние и последние внешние команды используют Win32 API. Это основано на последнем разделе, касающемся разработки консольного приложения от MSDN Globalization, шаг за шагом !
Поскольку по крайней мере win10 то, что отображается в консоли (одинаковая кодировка для всех выходных данных команды) и сохраняет файл, отличается (выходная кодировка изменяется в зависимости от команды), потоки вывода / ввода могут обрабатываться по-разному в зависимости от типа дескрипторов, на которые они указывают. Консольные функции могут использоваться для отображения и функций файла ввода / вывода в случае перенаправления. Спекуляция на основе высокоуровневых консольных функций ввода и вывода !
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 реализовала это.