Process.StartInfo.Arguments是否支持UTF-8字符串?

15

您能将UTF-8字符串用作StartInfo的参数吗?

我正在尝试将UTF-8字符串(在这种情况下是日语字符串)作为控制台参数传递给一个应用程序。

就像这样(这只是一个示例!(cmd.exe将是自定义应用程序))

var process = new System.Diagnostics.Process();
process.StartInfo.Arguments = "/K \"echo これはテストです\"";
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = true;

process.Start();
process.WaitForExit();

执行此命令似乎会丢失UTF-8字符串,目标应用程序看到的只是“echo ?????????”

当直接在命令行上执行此命令(通过粘贴参数)时,即使命令行本身似乎无法正确显示它,目标应用程序也能正确接收到该字符串。

我需要采取特殊措施来启用参数的UTF-8支持,还是根本不支持?

4个回答

7

程序的命令行采用UTF-16编码,与.NET字符串相同:

Arguments = "/U /K \"echo これはテストです> output.txt\"";

这是控制台窗口,无法显示超出其当前代码页/所选字体范围的字符。但是,我假设您不想调用echo,因此这完全取决于您要调用的程序的编写方式。
一些背景信息:使用“窄”(系统代码页)入口点(例如main(int argc, char** argv))而不是“宽”(UTF-16)入口点(wmain(int argc, wchar_t** argv))的C或C++程序将由一个存根调用,将命令行转换为系统代码页 - 该代码页不能是UTF-8。
到目前为止,最好的选择是更改程序以使用宽入口点,并简单地获得与您在.NET字符串中相同的UTF-16。如果不可能,那么可以尝试的一个技巧是传递一个UTF-16命令行,当转换为系统代码页时,其中包含您要使用的UTF-8字符。
Arguments = Encoding.Default.GetString(Encoding.UTF8.GetBytes(args));

程序员注意:如果在您或他人的机器上出现严重错误,不要感到惊讶,这取决于当前系统代码页中的每个可能的字节是否有效,系统代码页与启动程序时不同,运行的程序未使用该数据进行任何编码相关的Windows函数(带有A、W后缀的版本),等等。


是的,我可以看到程序以Unicode接收它们的命令行,但我不知道Process类的StartInfo.Arguments是否能将该值传递给应用程序。在我的测试中似乎并不是这样。 - Patrick Klug
@Patrick:要完全准确,当程序启动后,它从Windows接收到的原始值总是Unicode编码。根据它是如何编写的,它可能会在看到它之前将其转换为系统代码页。 - Simon Buchan
如果您使用main作为入口点,仍然可以使用GetCommandLine(http://msdn.microsoft.com/en-us/library/ms683156(VS.85).aspx)获取UTF-16参数。这是Qt的QCoreApplication在Windows上的工作方式。 - Patrick

3
这完全取决于您要启动的程序。Process类完全支持Unicode,操作系统也是如此。但是该程序可能是旧的,并且使用8位字符。 它将使用GetCommandLineA()检索命令行参数,即原生Unicode GetCommandLineW()API函数的ANSI版本。 然后使用控制面板+区域和语言选项,非Unicode程序的语言配置的系统默认代码页将Unicode字符串转换为8位字符。 使用CP_ACP的WideCharToMultiByte()。
如果那不是日语代码页,则翻译会产生问号,因为日语字形仅在日语代码页中具有代码。 对于非日语用户来说,切换系统代码页通常不是很理想。 Utf8肯定不起作用,程序不会期望它们。 考虑在虚拟机中运行此程序。

1
我刚刚创建了一个Windows Forms应用程序,它在RichTextBox中显示Environment.CommandLine字符串,并且该字符串被正确地显示出来,因此可以通过这种方式传递Unicode字符串。
我认为我的操作系统默认使用代码页1252,因此即使像您所做的那样粘贴参数,也无法在命令提示符中显示这些字符。

你是通过使用Process和ProcessStartInfo启动应用程序还是直接从命令行传递参数给它的? - Patrick Klug
我使用了Process / ProcessStartInfo - 我只是将“cmd.exe”更改为我的WinForms应用程序的“test.exe”。 - C.Evenhuis

0

使用的字符串[System.String或简单的string]都是基于Unicode的。因此,是的,它们可以支持上述编码。

这里看一下

您需要检查与操作系统相关的设置(代码页、语言等)。


我知道字符串支持Unicode——我只是不确定ProcessStartInfo的Arguments属性是否正确地将其传播到执行的应用程序。似乎并没有。 - Patrick Klug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接