将Unicode命令行参数传递给控制台应用程序

3
我正在尝试编写一个控制台应用程序,可以接受文件名参数,并希望它能够处理Unicode文件名。问题是我不知道如何测试它。
如何将Unicode参数传递给控制台应用程序?
我尝试创建一个调用程序并传递一些Unicode字符的Unicode批处理文件,但它不起作用;命令提示符无法启动该程序,因为它在文件名中遇到了null字符。我尝试将代码页更改为65001,并在命令行上使用Alt键输入Unicode字符,但也没有成功。
下面是一个示例程序。我正在寻找一种方法来获得以下输出:
C:\> unicodeargtest Foobar
46, 0, 6f, 0


// UnicodeArgTest.cpp
#define UNICODE
#include <tchar.h>
#include <stdio.h>
int wmain (int argc, wchar_t**argv) {
    printf("%x, %x, %x, %x\n", argv[1][0], argv[1][1], argv[1][2], argv[1][3]);
}

cmd.exe 支持 Unicode 吗?我认为不支持(因为要兼容旧的 DOS 程序)。也许问题就出在这里,所以尝试使用 MS PowerShell。 - Raxillan
@Raxillan:确实如此。CDM.EXE与旧的DOS程序不兼容,它完全是32位(或64位)。它确实与批处理文件有一些兼容性,但DOS批处理文件是基于ASCII文本的,而ASCII是Unicode的子集。 - MSalters
@MSalters,仅在Windows 7中还是之前的版本也适用?所以:您认为在命令行中键入“chcp 65001”并插入一些Unicode符号是否有效?据我了解,作者尝试过这样做,但没有结果。 - Raxillan
@Raxillan:不,CHCP 不是正确的方法。65001 是 UTF-8 的代码页,但 Windows 使用 UTF-16 进行 Unicode 编码。CHCP 只适用于双字节字符集,而 UTF-8 可以使用多达 4 个字节。这在从 NT 3.1 到 8 版本中都是一样的。 - MSalters
@Raxillan:不存在。CMD.EXE 支持 Unicode,但不支持 UTF-8。你的备选方案 MS PowerShell 使用 .Net 字符串,它们也是 UTF-16。 - MSalters
显示剩余2条评论
2个回答

2
哦,糟糕!又发生了。我来自汇编语言的背景,因此偶尔会被一些 C++ 的东西绊倒。我经常忘记的一件事是在 C++ 中,编译器会自动补偿类型大小,计算索引、指针等。
例如:
DWORD dwa[4] = {1,2,3,4};
//dwa[2] references the third DWORD in the array (i.e., the ninth BYTE),
//NOT the second BYTE in the array

或者

struct EGS {
    char  str[5];
    int   num;
};
EGS   eg = {0};
EGS* peg = &eg;
peg++;
//peg is incremented by a whole EGS’ worth of bytes, NOT just 1
//for EGS, it is increased by 12 (5+4=9, rounded to the nearest 4, equals 12)

在这种情况下,因为参数被解释为宽字符(2字节),argv [1] [1] 不是空字符,而是第二个 Unicode 字符。
使用原始程序并传递一个 Unicode 字符,我得到了这个结果:
C:\>unicodeargtest ‽‽‽‽
203d, 203d, 203d, 203d

我只是将感叹问号粘贴到命令提示符中。在我的正常命令提示符模式下(使用光栅字体和代码页437),它们显示为?而不是,但结果仍然相同。
通过将参数转换为charBYTE
printf("%x, %x, %x, %x\n",
    ((BYTE*)(argv[1]))[0], ((BYTE*)(argv[1]))[1],
    ((BYTE*)(argv[1]))[2], ((BYTE*)(argv[1]))[3]
);

我得到了预期的结果:
C:\>unicodeargtest ‽‽‽‽
3d, 20, 3d, 20

C:\>unicodeargtest Foobar
46, 0, 6f, 0

粘贴Unicode字符可以正常工作,但使用批处理文件仍然不行。使用Unicode编码的批处理文件由于空字符的解释错误而存在问题,并且将其保存为UTF-8会导致它根本无法运行

记录一下,这不是C++的特性。C的行为完全相同。 - Harry Johnston
这并不是什么大发现!我知道的每种语言都这样做。 - David Heffernan
批处理文件应该支持Unicode。尝试使用记事本的“另存为Unicode”功能,这样可以得到正确的格式(确切地说,是带有字节顺序标记)。 - MSalters
@MSalters,你试过了吗?我试过了,就像我说的那样,它没有起作用;程序名称包含空字符:'■u'不被识别为内部或外部命令,可执行程序或批处理文件。(在“u”之前的字符是一个空字符。) - Synetech
嗯,不对,我有点想错了。你说得对 - 它并不像我想的那样工作。CMD.EXE在其“TYPE”命令和其他命令中支持Unicode,但并非所有地方都支持。因此,即使它可以正确显示批处理文件的内容,它也无法运行它。:\ - MSalters

1

拖放应该能解决问题。在资源管理器中,将要作为参数传递的文件拖到测试可执行文件上。(您可能首先想要更改可执行文件,使其在退出之前等待。)


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