Почему происходит сбой csc.exe, когда я в последний раз оставлял выходную кодировку как UTF8?

У меня есть или я столкнулся с очень странной вещью.

Интересно, есть ли у других и почему это происходит.

Запустив однострочную программу с этой строкой System.Console.WriteLine(System.Console.OutputEncoding.EncodingName);, я вижу, что кодировка Western European (DOS)

Отлично

Вот список некоторых кодовых страниц 1200 Unicode и 65001 utf-8 и Windows-1252 Western European (Windows) и 850 Western European DOS из https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx

Скажем, я пишу программу C-sharp, чтобы изменить кодировку на utf-8.

class sdf
{
  static void Main(string[] args)
{
System.Console.WriteLine(System.Console.OutputEncoding.EncodingName);
  System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(65001);
System.Console.WriteLine(System.Console.OutputEncoding.EncodingName);
}
}

Работает, печатает

Western European (DOS)
Unicode (UTF-8)

Теперь, когда я снова запускаю csc, csc падает.

введите здесь описание изображения

Проверил оперативку 14 часов, 8 проходов, мемтестом. Я запустил chkdsk на своем жестком диске, все в порядке. И это точно не те, это вопрос кодировки. Я знаю это, потому что если я открою новую командную строку, а затем запущу csc, она не сработает.

Таким образом, запуск этой программы c Sharp изменяет оболочку таким образом, что в следующий раз, когда просто запускается csc, происходит сбой самой csc, в такой большой степени.

Если я скомпилирую приведенный ниже код, а затем запущу его, затем запущу csc, затем запущу csc или csc какой угодно.cs, я получу сбой csc.

Поэтому закройте командную строку, откройте новую.

На этот раз поэкспериментируйте с комментарием и раскомментированием второй строки программы.

Я обнаружил, что если есть вторая строка (строка, которая меняет кодовую страницу на 850 (DOS, Западная Европа), то она не сработает при следующем запуске csc.

Принимая во внимание, что если я закомментирую эту вторую строку, программа завершится с изменением кодовой страницы/кодировки на UTF-8, а затем при следующем запуске csc произойдет сбой csc.

// раскомментируйте последнюю строку, а затем // это запустится, но в следующий раз вызовет сбой csc.

class asdf
{
  static void Main()
  {

     System.Console.OutputEncoding = System.Text.Encoding.UTF8; //output and to utf8
     System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(850); 
  }
}

Я не единственный человек, который столкнулся с чем-то подобным

хотя никаких объяснений там не было найдено -немедленно-вылетает-при-запуске-в-кодовой-странице-65001-utf8?forum=csharpgeneral" rel="nofollow noreferrer">https://social.msdn.microsoft.com/Forums/vstudio/en-US/ 0e5f477e-0c32-4e88-acf7-d53d43d5b566/c-командная-строка-компилятор-cscexe-немедленно-сбой-при-запуске-в-кодовой-странице-65001-utf8?forum=csharpgeneral

Я могу справиться с этим, убедившись, что последняя строка устанавливает кодовую страницу на 850. Хотя, как я объясню, это неадекватное решение.

Также я хотел бы знать, является ли это какой-то проблемой с CSC, которая есть и у других. Или любые другие решения.

добавлено

uuu1.cs

// uuu1.cs
class asdf
{
static void Main()
{

System.Console.InputEncoding  = System.Text.Encoding.UTF8;
System.Console.OutputEncoding = System.Text.Encoding.UTF8;

// not unicode.  UTF8 means redirection will then work

System.Console.WriteLine("ჵ");

// try redirecting too..

// and try  checking for csc crash or not
//System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(850);
//System.Console.InputEncoding =System.Text.Encoding.GetEncoding(850);
//problem is that when that is commented, it breaks the redirection



}
}

Добавление строки / раскомментировать последние строки, поэтому у меня есть

System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(850);

остановил бы сбой, но это неадекватное решение, потому что, например.. Если я хочу перенаправить вывод программы в файл, то мне нужно UTF8 от начала до конца, иначе это не работает

это работает с раскомментированной строкой кодовой страницы 850

c:\blah>uuu1>r.r<ENTER>  
c:\blah>type r.r <ENTER>  
c:\blah>ჵ  

Если я раскомментирую последние строки, тем самым изменив кодовую страницу на 850, тогда csc не вылетит при следующем запуске, но перенаправление не работает, и r.r не содержит этого символа.

Добавлено 2

Ответ Хана заставляет меня заметить еще один способ вызвать эту ошибку.

C:\Users\harvey\somecs3>csc<ENTER>
Microsoft (R) Visual C# Compiler version 4.0.30319.18408
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

warning CS2008: No source files specified
error CS1562: Outputs without source must have the /out option specified

C:\Users\harvey\somecs3>chcp  65001<ENTER>
Active code page: 65001

C:\Users\harvey\somecs3>csc<ENTER>  <-- CRASH

C:\Users\harvey\somecs3>

person barlop    schedule 20.06.2015    source источник
comment
Как вы скомпилируете и запустите это?   -  person CodeCaster    schedule 20.06.2015
comment
@CodeCaster поместил код в файл с расширением .cs, например. aaa1.cs затем запустите csc aaa1.cs   -  person barlop    schedule 20.06.2015
comment
Командная строка разработки @CodeCaster или обычная командная строка имеют ту же проблему. Кстати, я тоже установил шрифт. Шаги по изменению шрифта описаны techrepublic.com/blog/windows-and-office/   -  person barlop    schedule 20.06.2015
comment
@CodeCaster процесс добавления шрифтов в командную строку сам по себе был бы довольно длинным постом. пост удвоился бы в размере, поэтому я дал ссылку на статью об этом. И многие люди, знакомые с этой проблемой, в любом случае добавят шрифты Unicode в командную строку. Проблема здесь с csc.exe, а не с добавлением шрифтов в командную строку. Можно было бы сделать это без добавления шрифтов в командную строку, просто это не так ясно.   -  person barlop    schedule 20.06.2015
comment
отчет об ошибке здесь connect.microsoft.com/VisualStudio/feedback/details/2632278   -  person barlop    schedule 26.04.2016
comment
А, это объясняет! Мне было интересно, почему csc из .NET 3+ продолжал падать. Как только я увидел этот пост, я вспомнил, что find также дает сбой, когда используется кодовая страница Unicode (chcp 65001), и действительно, изменение кодовой страницы на 437 позволяет csc работать без сбоев. Очень плохо, что собственные программы Microsoft не могут обрабатывать Unicode. ¬_¬   -  person Synetech    schedule 20.05.2021
comment
@Synetech не только это, но и команда chcp довольно неясна и вводит в заблуждение, см. последний абзац в ответе sstan   -  person barlop    schedule 21.05.2021


Ответы (2)


Что ж, вы нашли ошибку в том, как компилятор C# справляется с необходимостью вывода текста на консоль при переключении на UTF-8. Он имеет самодиагностику, чтобы убедиться, что преобразование из строки в кодировке UTF-16 в кодовую страницу вывода консоли работает правильно, он нажимает большую красную кнопку, когда это не так. Трассировка стека выглядит так:

csc.exe!OnCriticalInternalError()  + 0x4 bytes  
csc.exe!ConsoleOutput::WideToConsole()  + 0xdc51 bytes  
csc.exe!ConsoleOutput::print_internal()  + 0x2c bytes   
csc.exe!ConsoleOutput::print()  + 0x80 bytes    
csc.exe!ConsoleOutput::PrintString()  + 0xb5 bytes  
csc.exe!ConsoleOutput::PrintBanner()  + 0x50 bytes  
csc.exe!_main()  + 0x2d0eb bytes    

Фактический код для WideToConsole() недоступен, наиболее близким соответствием является эта версия из дистрибутива SSCLI20:

/*
 * Like WideCharToMultiByte, but translates to the console code page. Returns length,
 * INCLUDING null terminator.
 */
int ConsoleOutput::WideCharToConsole(LPCWSTR wideStr, LPSTR lpBuffer, int nBufferMax)
{
    if (m_fUTF8Output) {
        if (nBufferMax == 0) {
            return UTF8LengthOfUnicode(wideStr, (int)wcslen(wideStr)) + 1; // +1 for nul terminator
        }
        else {
            int cchConverted = NULL_TERMINATED_MODE;
            return UnicodeToUTF8 (wideStr, &cchConverted, lpBuffer, nBufferMax);
        }

    }
    else {
        return WideCharToMultiByte(GetConsoleOutputCP(), 0, wideStr, -1, lpBuffer, nBufferMax, 0, 0);
    }
}

/*
 * Convert Unicode string to Console ANSI string allocated with VSAlloc
 */
HRESULT ConsoleOutput::WideToConsole(LPCWSTR wideStr, CAllocBuffer &buffer)
{
    int cch = WideCharToConsole(wideStr, NULL, 0);
    buffer.AllocCount(cch);
    if (0 == WideCharToConsole(wideStr, buffer.GetData(), cch)) {
        VSFAIL("How'd the string size change?");
        // We have to NULL terminate the output because WideCharToMultiByte didn't
        buffer.SetAt(0, '\0');
        return E_FAIL;
    }
    return S_OK;
}

Сбой происходит где-то вокруг утверждения VSFAIL(), судя по машинному коду. Я вижу оператор return E_FAIL. Однако он был изменен по сравнению с версией, которую я опубликовал, оператор if() был изменен, и похоже, что VSFAIL() был заменен на RETAILVERIFY(). Что-то сломалось, когда они внесли эти изменения, возможно, в UnicodeToUTF8(), который теперь называется UTF16ToUTF8(). Еще раз подчеркну, что версия, которую я разместил, на самом деле не дает сбоев, вы можете убедиться сами, запустив C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe. Эта ошибка есть только в версии v4 csc.exe.

Настоящую ошибку трудно обнаружить в машинном коде, лучше пусть об этом побеспокоится Microsoft. Вы можете сообщить об ошибке на сайте connect.microsoft.com. Я не вижу отчета, похожего на него, довольно примечательного, кстати. Обходной путь для этой ошибки — использовать CHCP для обратного изменения кодовой страницы.

person Hans Passant    schedule 20.06.2015
comment
Мой Microsoft (R) Visual C# Compiler version 4.0.30319.18408 - person barlop; 20.06.2015
comment
Единственная кнопка отправки сообщения об ошибке, которую я вижу, находится на собственной странице microsoft.net connect.microsoft.com/VisualStudio. /MSNetNative И это просто переходит на страницу с ошибкой, ошибка, пытающаяся отправить ошибку! i.imgur.com/Rxy8bW9.png, возможно, в другом месте есть опция отправки сообщения об ошибке, которая работает - person barlop; 20.06.2015
comment
Выглядит хорошо, когда я пытаюсь это сделать. Вы должны войти в систему. - person Hans Passant; 20.06.2015
comment
[для сравнения] Если я нажму на powershell в каталоге, появится кнопка для отправки сообщения об ошибке. Если я нажму на Visual Studio, я получу сообщение о том, что вас пригласили присоединиться к частной программе NDA для Visual Studio, вы можете просмотреть определенный контент, выбрав из раскрывающегося списка «Программы», расположенного в верхней части этой страницы. в этот момент я понятия не имею, что щелкнуть дальше, но щелчок по программам, похоже, не очень помогает. - person barlop; 20.06.2015
comment
вы можете отправить его или если вы видите опцию отправки ошибки, дайте мне знать.. Кстати, еще одна забавная вещь, хотя да, chcp 850 работает.. Если делать chcp непосредственно перед выполнением chcp 850, он говорит, что кодовая страница 850. Итак, почему chcp 850 имеет значение, я не знаю, если он уже на 850 в соответствии с chcp. - person barlop; 20.06.2015
comment
Я отправил отчет об ошибке сейчас. Но на самом деле вам действительно нужно выйти, затем перейдите на connect.microsoft.com/VisualStudio, затем нажмите "Отправить". ошибка, то он предлагает войти в систему,. и он дает форму обратной связи для отправки сообщения об ошибке. Но при входе в систему при переходе по этому URL-адресу выдается ошибка. webapps.stackexchange.com/questions/79495/ - person barlop; 22.06.2015
comment
@barlop, ваш код изменяет только выходную кодовую страницу, то есть SetConsoleOutputCP, но запуск chcp.com проверяет только входную кодовую страницу, то есть GetConsoleCP. Запуск chcp.com 850 изменяет как входную, так и выходную кодовые страницы, то есть вызывает SetConsoleCP и SetConsoleOutputCP. Кстати, использование кодовой страницы 65001 в консоли имеет много ошибок в разных версиях Windows от XP до Windows 10 — некоторые в conhost.exe (возможно, condrv.sys в Windows 8+), а некоторые в среде выполнения C или другой библиотеке. Если вам нужен Unicode в консоли, вы должны использовать [W]ide API. - person Eryk Sun; 25.06.2015
comment
@eryksun очень интересные моменты, которые вы делаете, и перепроверяете только ввод. Я не могу найти многого в [W]ide API. Как бы я использовал [W]ide API в C Sharp, например. установить кодовую страницу на UTF8? - person barlop; 27.06.2015
comment
@barlop, установите кодировку ввода и вывода на System.Text.Encoding.Unicode. С этим параметром Console.ReadLine вызывает Win32 ReadConsoleW, а Console.WriteLine вызывает Win32 WriteConsoleW. Обратите внимание, что кодировки, отличные от Unicode, вызывают ReadFile, который имеет специальную обработку для Ctrl+Z в начале строки, но ReadConsole этого не делает. - person Eryk Sun; 27.06.2015
comment
@eryksun Спасибо .. И где это задокументировано о том, что System.Text.Encoding.Unicode заставляет Console.ReadLine вызывать Win32 ReadConsoleW? System.Console.InputEncoding=System.Text.Encoding.UTF8 Я заметил, что chcp по-прежнему показывает 65001 для этого. И все еще есть ошибка сбоя csc. С .Unicode chcp не изменяется, и csc не падает. Но тогда, если я делаю myprog>a.a, он не будет перенаправлять иностранные символы, если я не сделаю UTF8, который кажется 65001. - person barlop; 27.06.2015
comment
@barlop, когда вы перенаправляете на канал или файл, он пишет UTF-16 без спецификации (т. Е. "\uFEFF"), поэтому некоторые программы могут не определять кодировку текста. Если System.Console.IsOutputRedirected, вы можете написать спецификацию в этом случае или переключиться на UTF-8, если хотите. - person Eryk Sun; 27.06.2015

Есть разные статьи, которые намекают на то, что в консоли Windows есть много ошибок, связанных с Unicode. Такие статьи, как: https://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/

Вот один обходной путь, который работает для меня. Вместо:

csc aaa1.cs

Попробуйте это (что перенаправит вывод CSC в файл):

csc /utf8output aaa1.cs > aaa1-compilation.log

Соответствующая документация: https://msdn.microsoft.com/en-us/library/d5bxd1x2.aspx

В некоторых международных конфигурациях выходные данные компилятора не могут правильно отображаться в консоли. В этих конфигурациях используйте /utf8output и перенаправляйте вывод компилятора в файл.

добавлено Барлопом

просматривая чат, мы обнаружили, что выполнение csc uuu1.cs<ENTER> uuu1<ENTER> затем, чтобы предотвратить сбой, каждый следующий csc должен выполняться с /utf8output И (по какой-то странной неизвестной причине), как ни странно, с перенаправлением .. так что, csc /utf8output uuu1.cs >asdfsdaf

Однако обходной путь Хана лучше: просто запустите chcp 850 (или любую другую кодовую страницу, которую вы используете) после uuu1<ENTER>, даже если chcp говорит, что это 850, вам все равно нужно выполнить chcp 850. Тогда csc будет работать нормально.

Причина, по которой при возникновении проблемы вы должны запустить chcp 850, даже если chcp показывает 850, заключается в том, что chcp покажет вам только входную кодировку, хотя chcp 850 изменит как входную, так и выходную кодировку, и мы хотим, чтобы изменение кодировки вывода. Таким образом, chcp может показывать 850, даже если ваша выходная кодировка равна 65001, и проблема заключается только в том, что выходная кодировка равна 65001.

person sstan    schedule 20.06.2015
comment
не работает i.imgur.com/JPa9xlD.png и даже делать это точно так, как вы есть .. В файле aaa1-compilation.log нет ошибок, он просто содержит вывод первого запуска компилятора. запуск csc‹ENTER› после этого, что бы ни было после csc, что-то или ничего после csc, не работает, происходит сбой - person barlop; 20.06.2015
comment
Извините, я немного запутался. Изображение, на которое вы ссылаетесь, показывает, что вы выполнили команду csc с параметром utf8output, но я не вижу, чтобы вы перенаправляли вывод в файл. Можете ли вы уточнить, что именно вы пробовали? В моих тестах единственный способ заставить CSC работать с консолью utf-8 — это выполнить эти две вещи в комбинации: параметр utf8output + перенаправление вывода в файл. - person sstan; 20.06.2015
comment
i.imgur.com/WgfgqlS.png ‹ -- перенаправление, с которым у меня возникла проблема, uuu›file, но я получу сбой даже без перенаправления. А вылет - второй запуск csc, после запуска программы. Как показано на этом скриншоте. Причина, по которой я хочу UTF8, заключается в том, что перенаправление работает с UTF8. Проблема в том, что csc вылетает при втором запуске. - person barlop; 20.06.2015
comment
Перенаправление (файл uuu1›), упомянутое в одном из моментов моего вопроса, работает (всегда работало), потому что оно работает, когда у меня установлена ​​​​кодировка UTF8. Но проблема в том, что наличие UTF8 приводит к csc, а затем к сбою при следующем запуске. - person barlop; 20.06.2015
comment
Хорошо, и я согласен с вами. Я просто предлагаю вам запустить CSC с перенаправлением и для вашего второго запуска в качестве обходного пути. Когда консоль находится в режиме UTF-8, я также не могу заставить ее нормально работать. С этого момента я постоянно звоню csc /utf8output test.cs > test.log, чтобы избежать сбоя. Вам это как-то помогает? Или вы хотите иметь возможность просто выполнить csc test.cs для второго запуска без каких-либо дополнительных параметров или перенаправлений? - person sstan; 20.06.2015
comment
И просто чтобы убедиться, что я не путаю вас. Я говорю о перенаправлении вывода вызова CSC. Не перенаправлять вывод вашей программы. - person sstan; 20.06.2015
comment
Давайте продолжим обсуждение в чате. - person barlop; 20.06.2015
comment
люди могут обратиться к чату для получения дополнительной информации ... но я просто отмечу здесь. Этот обходной путь работает. Хотя, как мы видим, обходной путь Ганса и копание имеют преимущество. Итак, +1 и +1 для Ганса, и я приму обходной путь/решение Ганса как лучший - person barlop; 20.06.2015