bar*_*lop 4 c# windows command-line csc
我正在遇到或遇到过一件非常奇怪的事情.
我想知道其他人是否有,以及为什么会这样.
使用此行运行单行程序后,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);
}
}
Run Code Online (Sandbox Code Playgroud)
它工作,它打印
Western European (DOS)
Unicode (UTF-8)
Run Code Online (Sandbox Code Playgroud)
现在当我再次运行csc时,csc崩溃了.

我检查了我的内存14小时,8次通过,记忆了.我跑了chkdsk我的硬盘,一切都很好.这绝对不是那些,这是一个编码问题.我知道,因为如果我打开一个新的cmd提示符,然后运行csc,它不会崩溃.
所以运行那个急剧的程序,改变shell,这样下一次运行csc就会以很大的方式崩溃csc.
如果我编译下面的代码,然后运行它,然后运行csc,然后运行csc,或csc whatever.cs,我得到csc崩溃.
关闭cmd提示符,打开一个新提示符.
这一次,尝试评论并取消注释程序的第二行
我发现,如果第二行(将代码页更改为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);
}
}
Run Code Online (Sandbox Code Playgroud)
我不是唯一一个碰到这样的人
我可以通过确保最后一行将代码页设置为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
}
}
Run Code Online (Sandbox Code Playgroud)
添加行/取消注释最后一行,所以我有
System.Console.OutputEncoding = System.Text.Encoding.GetEncoding(850);
会停止崩溃,但这是一个不充分的解决方案,因为例如..如果我想将程序的输出重定向到文件,那么我从头到尾一直需要UTF8,否则它不起作用
这适用于代码页850行未注释
c:\blah>uuu1>r.r<ENTER>
c:\blah>type r.r <ENTER>
c:\blah>?
Run Code Online (Sandbox Code Playgroud)
如果我取消注释最后一行,从而将代码页更改为850,那么确保csc在下次运行时不会崩溃,但重定向不起作用且rr不包含该字符.
新增2
Han的回答让我注意到另一种触发此错误的方法
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>
Run Code Online (Sandbox Code Playgroud)
好吧,你发现了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
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
从机器代码判断,崩溃发生在VSFAIL()断言的某处.我可以看到返回E_FAIL语句.但是,从我发布的版本改变了,if()语句被修改了,看起来VSFAIL()被RETAILVERIFY()取代了.当他们做出这些更改时可能会出现问题,可能是在UnicodeToUTF8()中,现在名为UTF16ToUTF8().再次强调,我发布的版本实际上并没有崩溃,您可以通过运行C:\ Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe自行查看.只有vc版本的csc.exe有此错误.
实际的bug很难从机器代码中挖掘出来,最好让微软担心.您可以在connect.microsoft.com上提交错误.我没有看到类似它的报告,相当不错的顺便说一句.此错误的解决方法是使用CHCP更改代码页.