我们在Team Foundation Server(TFS)中有一个项目,其中包含非英语字符(š).当我试图编写一些与构建相关的东西时,我们偶然发现了一个问题 - 我们无法将š字母传递给命令行工具.命令提示符或其他什么不是搞砸了,并且tf.exe实用程序找不到指定的项目.
我已经尝试了.bat文件的不同格式(ANSI,带有和不带BOM的 UTF-8 )以及用JavaScript编写脚本(这本身就是Unicode) - 但没有运气.如何执行程序并将其传递给Unicode命令行?
尝试:
chcp 65001
这会将代码页更改为UTF-8.此外,您需要使用Lucida控制台字体.
我的背景:我在控制台中使用Unicode输入/输出多年(并且每天都做很多.此外,我正在为这项任务开发支持工具).只要您了解以下事实/限制,就会遇到很少的问题:
CMD
和"控制台"是无关的因素. CMD.exe
是一个准备"在控制台内"工作的程序("控制台应用程序").
AFAIK,CMD
完全支持Unicode; 您可以在任何代码页处于活动状态时输入/输出所有Unicode字符.
Windows的控制台有很多对Unicode的支持 - 但它并不完美(只是"足够好";见下文).
chcp 65001
是非常危险的.除非程序是专门设计用于解决Windows API中的缺陷(或使用具有这些变通方法的C运行时库),否则它将无法可靠地工作. Win8修复了这些问题的½ cp65001
,但其余的仍然适用于Win10.
我在工作cp1252
.正如我已经说过:要在控制台中输入/输出Unicode,不需要设置代码页.
细节
要将Unicode读/写到控制台,应用程序(或其C运行时库)应足够智能,不能使用File-I/O
API,而应使用Console-I/O
API.(例如,看看Python是如何做到的.)
同样,要读取Unicode命令行参数,应用程序(或其C运行时库)应足够智能以使用相应的API.
控制台字体渲染仅支持BMP中的Unicode字符(换句话说:下面U+10000
).仅支持简单的文本呈现(因此欧洲 - 以及一些东亚语言 - 应该可以正常工作 - 只要使用预先组合的表单).[有一个轻微的小字这里东亚和字符U + 0000,U + 0001,U + 30FB.]
实际考虑
Window上的默认值不是很有用.为了获得最佳体验,应该调整3个配置:
输出:全面的控制台字体.为了获得最佳效果,我推荐我的版本.(安装说明存在于此页面中,并在本页的其他答案中列出.)
输入:有能力的键盘布局.为了获得最佳效果,我推荐我的布局.
对于输入:允许Unicode的HEX输入.
还有一个问题是"粘贴"到控制台应用程序中(非常技术性):
HEX输入提供上的字符KeyUp
的Alt
; 所有其他提供角色的方式都会发生KeyDown
; 如此多的应用程序还没有准备好看到一个角色KeyUp
.(仅适用于使用Console-I/O
API的应用程序.)
结论:许多应用程序不会对HEX输入事件做出反应.
此外,"粘贴"字符所发生的情况取决于当前的键盘布局:如果可以在不使用前缀键的情况下键入字符(但使用任意复杂的修饰符组合,Ctrl-Alt-AltGr-Kana-Shift-Gray*
则如此),则会在模拟按键上传递.这是任何应用程序所期望的 - 所以粘贴任何只包含这些字符的东西都可以.
但是,通过模拟HEX输入来传递"其他"字符.
结论:除非您的键盘布局支持输入大量没有前缀键的字符,否则当您通过Console的UI时,一些错误的应用程序可能会跳过字符Paste
:Alt-Space E P
.(这就是我推荐使用键盘布局的原因!)
还应该记住,Windows的"替代","更有能力"的控制台根本不是游戏机.它们不支持Console-I/O
API,因此依赖这些API工作的程序将无法运行.(但是,只使用"文件I/O API到控制台文件句柄"的程序可以正常工作.)
这种非控制台的一个例子是MicroSoft的一部分Powershell
.我不用这个; 进行实验,按下并释放WinKey
,然后键入powershell
.
(另一方面,有一些程序,例如ConEmu
或ANSICON
试图做更多的程序:它们"试图"拦截Console-I/O
API以使"真正的控制台应用程序"也起作用.这绝对适用于玩具示例程序;在现实生活中,这可能或可能无法解决您的特定问题.实验.)
设置字体,键盘布局(以及可选的,允许HEX输入).
仅使用通过Console-I/O
API的程序,并接受Unicode命令行参数.例如,任何cygwin
编译的程序应该没问题.正如我已经说过的,CMD
也很好.
UPD:最初,对于一个错误cp65001
,我混淆了内核和CRTL层(UPD²:和Windows用户模式API!). 另外: Win8修复了这个bug的一半; 我澄清了关于"更好的控制台"应用程序的部分,并添加了对Python如何做的参考.
我有同样的问题(我来自捷克共和国).我有一个Windows的英文版,我必须使用共享驱动器上的文件.文件的路径包括特定于捷克语的字符.
适合我的解决方案是:
在批处理文件中,更改charset页面
我的批处理文件:
chcp 1250 copy "O:\VE?EJNÉ\ŽŽŽŽŽŽ\Ž.xls" c:\temp
批处理文件必须保存在CP 1250中.
请注意,控制台不会正确显示字符,但它会理解它们......
检查非Unicode程序的语言.如果您在Windows控制台中遇到俄语问题,那么您应该在这里设置俄语:
实际上,诀窍是命令提示符实际上理解这些非英文字符,只是无法正确显示它们.
当我在命令提示符中输入包含一些非英语字符的路径时,它显示为"?? ?????? ?????".当你提交你的命令(cd"??? ?????? ?????"在我的情况下),一切都按预期工作.
更改Windows控制台的默认代码页非常困难.当您在网上搜索时,您会发现不同的提案,但有些提案可能会完全破坏您的Windows,即您的PC无法再启动.
最安全的解决方案是:转到您的注册表项HKEY_CURRENT_USER\Software\Microsoft\Command Processor
并添加String value Autorun
= chcp 65001
.
或者,您可以将这个小型Batch脚本用于最常见的代码页.
@ECHO off SET ROOT_KEY="HKEY_CURRENT_USER" FOR /f "skip=2 tokens=3" %%i in ('reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v OEMCP') do set OEMCP=%%i ECHO System default values: ECHO. ECHO ............................................... ECHO Select Codepage ECHO ............................................... ECHO. ECHO 1 - CP1252 ECHO 2 - UTF-8 ECHO 3 - CP850 ECHO 4 - ISO-8859-1 ECHO 5 - ISO-8859-15 ECHO 6 - US-ASCII ECHO. ECHO 9 - Reset to System Default (CP%OEMCP%) ECHO 0 - EXIT ECHO. SET /P CP="Select a Codepage: " if %CP%==1 ( echo Set default Codepage to CP1252 reg add "%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d "@chcp 1252>nul" /f ) else if %CP%==2 ( echo Set default Codepage to UTF-8 reg add "%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d "@chcp 65001>nul" /f ) else if %CP%==3 ( echo Set default Codepage to CP850 reg add "%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d "@chcp 850>nul" /f ) else if %CP%==4 ( echo Set default Codepage to ISO-8859-1 add "%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d "@chcp 28591>nul" /f ) else if %CP%==5 ( echo Set default Codepage to ISO-8859-15 add "%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d "@chcp 28605>nul" /f ) else if %CP%==6 ( echo Set default Codepage to ASCII add "%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d "@chcp 20127>nul" /f ) else if %CP%==9 ( echo Reset Codepage to System Default reg delete "%ROOT_KEY%\Software\Microsoft\Command Processor" /v AutoRun /f ) else if %CP%==0 ( echo Bye ) else ( echo Invalid choice pause )
使用@chcp 65001>nul
而不是chcp 65001
抑制输出"活动代码页:65001",每次启动新的命令行窗口时都会得到.
可从代码页标识符获取的所有可用编号的完整列表
请注意,这些设置仅适用于当前用户.如果您想为所有用户设置它,请替换line SET ROOT_KEY="HKEY_CURRENT_USER"
bySET ROOT_KEY="HKEY_LOCAL_MACHINE"
在Windows 10 x64计算机上,我通过以下方式使命令提示符显示非英语字符:
打开提升的命令提示符(以管理员身份运行CMD.EXE).通过以下方式在注册表中查询可用的TrueType字体到控制台:
REG query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont"
您将看到如下输出:
0 REG_SZ Lucida Console 00 REG_SZ Consolas 936 REG_SZ *??? 932 REG_SZ *?? ????
现在我们需要添加一个支持Courier New所需字符的TrueType字体.我们通过在字符串名称中添加零来完成此操作,因此在这种情况下,下一个将是"000":
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont" /v 000 /t REG_SZ /d "Courier New"
现在我们实现UTF-8支持:
REG ADD HKCU\Console /v CodePage /t REG_DWORD /d 65001 /f
将默认字体设置为"Courier New":
REG ADD HKCU\Console /v FaceName /t REG_SZ /d "Courier New" /f
将字体大小设置为20:
REG ADD HKCU\Console /v FontSize /t REG_DWORD /d 20 /f
如果您愿意,可以快速编辑:
REG ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f
由于我没有看到Python 2.7的完整答案,我将概述两个重要步骤和一个非常有用的可选步骤.
您需要支持Unicode的字体.Windows附带Lucida控制台,可以通过右键单击命令提示符的标题栏并单击Defaults
选项来选择.这也可以访问颜色.请注意,您也可以通过选择更改以某些方式调用的命令窗口的设置(例如,在此处打开,Visual Studio)Properties
.
您需要将代码页设置为cp65001
,这似乎是Microsoft尝试为命令提示符提供UTF-7和UTF-8支持.chcp 65001
在命令提示符下运行来执行此操作.一旦设置,它将一直保持这种状态,直到窗口关闭.每次启动cmd.exe时都需要重做此操作.
有关更持久的解决方案,请参阅超级用户的此答案.简而言之,REG_SZ
使用regedit 创建一个(String)条目HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor
并命名它AutoRun
.将其值更改为chcp 65001
.如果您不想从命令中看到输出消息,请@chcp 65001>nul
改用.
有些程序无法与此编码进行交互,MinGW是一个值得注意的程序,在使用无意义的错误消息进行编译时失败.尽管如此,这种方法非常有效,并且不会导致大多数程序出现错误.