如何从 c# 中的 robocopy 过程标准输出中获取 unicode 字符

spa*_*lug 5 c# unicode stdout process robocopy

我们的应用程序运行各种操作并在日志窗口中显示输出。一种操作是使用robocopy在文件夹之间复制文件。

这可以正常工作,直到 robocopy 输出包含 unicode 字符。我知道我需要使用 /unicode 选项,但我似乎得到的只是胡言乱语。

这是我的简化代码示例:

class Program
{
    static void Main(string[] args)
    {


        StreamReader outputReader = null;
        StreamReader errorReader = null;


        using (Process process = new Process())
        {

            Encoding encoding = Encoding.Default;

            if (encoding != null)
            {
                process.StartInfo.StandardOutputEncoding = encoding;
                process.StartInfo.StandardErrorEncoding = encoding;
            }

            process.StartInfo.FileName = @"C:\Windows\system32\robocopy.exe";
            process.StartInfo.Arguments = @"""D:\temp\????????? ????????? ?????"" ""D:\temp\?????? ????????? ?????"" /unicode";
            process.StartInfo.ErrorDialog = false;
            process.StartInfo.LoadUserProfile = false;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;

            process.StartInfo.WorkingDirectory = @"D:\temp\????????? ????????? ?????";



            bool processStarted = process.Start();
            if (processStarted)
            {
                //Get the output stream
                outputReader = process.StandardOutput;
                errorReader = process.StandardError;
                process.WaitForExit();

                string standardOutput = outputReader.ReadToEnd();
                string errorOutput = errorReader.ReadToEnd();
                if (!string.IsNullOrEmpty(standardOutput))
                {

                    byte[] bytes = encoding.GetBytes(standardOutput);
                    byte[] convertedBytes = Encoding.Convert(encoding, Encoding.UTF8, bytes);

                    string convertedStandardOutput = Encoding.UTF8.GetString(convertedBytes);

                    Console.Write("Standard output: ");
                    Console.WriteLine(convertedStandardOutput);
                }
                if (!string.IsNullOrEmpty(errorOutput))
                {
                    Console.Write("Error output: ");
                    Console.WriteLine(errorOutput);
                }
            }

        }

        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了各种编码类型和转换都无济于事。这是我得到的输出类型:

standardOutput: "?????????????????????????????????????????†????††?›††??????????????†††††††††††††††?????????????????????????????????????????†????›????????????????†??????????????????????††???›?????????????????†???????††??????????????????????????????????????????????????????????????????????????????????????????????????†††††††††????????????????????????????????????????????????????????????†††††††???†????†?????????†????†????††???††††?††††?††††?††††?††††?††††??†???›††††‰††††‰††††‰††††‰††††‰††††?†????††††?††††?††††?††††?††††?††††??†???›†???‰†???‰†††††††††††???‰†????†????????????????????"


convertedStandardOutput: "?????????????????????????????????????????†????††?›††??????????????†††††††††††††††?????????????????????????????????????????†????›??????????`?????†??????????????????????††??4›?????????????????†???????††????????? ???????? ????????? ????????? ????       ????  ??????????????????????????????????????????†††††††††????????????????????????????????????????????????????????????†††††††???†????†?????????†???/†????††???††††?††††?††††?††††?††††?††††??†???›††††‰††††‰††††‰††††‰††††‰††††?†????††††?††††?††††?††††?††††?††††??†???›†???‰†???‰†††††††††††???‰†????†????????????????????"
Run Code Online (Sandbox Code Playgroud)

在命令窗口中运行时显示的输出是:

 ?
-------------------------------------------------- -----------------------------
   ROBOCOPY :: 适用于 Windows 的强大文件复制
-------------------------------------------------- -----------------------------

  开始时间:2015 年 3 月 16 日星期一 14:24:01
   来源:D:\temp\????????? ????????? ?????\
     目标:D:\temp\?????? ????????? ?????\

    文件:*.*

  选项 : * 。* / UNICODE / DCOPY : DA / COPY : DAT / R : 1 0 0 0 0 0 0 / W : 3 0

-------------------------------------------------- -----------------------------

                           0 D:\temp\????????? ????????? ?????\

-------------------------------------------------- -----------------------------

               总复制跳过不匹配失败额外
    目录:1 0 0 0 0 0
   文件:0 0 0 0 0 0
   字节:0 0 0 0 0 0
   时间:0:00:00 0:00:00 0:00:00 0:00:00
   结束 : 2015 年 3 月 16 日星期一 14:24:01

有任何想法吗?

Mic*_*Liu 3

看起来 /UNICODE 选项有问题:它在控制台输出中唯一影响的是行Options :。(您可以从字符之间的空格看出这部分是 Unicode,这是由额外的空字节引起的。) ROBOCOPY 似乎仍然使用系统代码页编写其他所有内容。但 /UNICODE 选项确实会导致 ROBOCOPY 在输出开头写出 Unicode 字节顺序标记,因此无论您设置什么 StandardOutputEncoding,StreamReader 都会切换到 Unicode。结果:乱码。

\n\n

使用 /UNILOG 选项代替 /UNICODE,该选项似乎可以正常工作(至少在 Windows 8.1 上):

\n\n
using (Process process = new Process())\n{\n    string logFileName = Path.GetTempFileName();\n    process.StartInfo.FileName = @"C:\\Windows\\system32\\robocopy.exe";\n    process.StartInfo.Arguments = @"""D:\\temp\\\xd0\xbd\xd0\xb5\xd0\xba\xd0\xbe\xd1\x82\xd0\xbe\xd1\x80\xd1\x8b\xd0\xb5 \xd1\x81\xd0\xbb\xd1\x83\xd1\x87\xd0\xb0\xd0\xb9\xd0\xbd\xd1\x8b\xd0\xb5 \xd0\xbf\xd0\xb0\xd0\xbf\xd0\xba\xd0\xb8"" ""D:\\temp\\\xd0\xb4\xd1\x80\xd1\x83\xd0\xb3\xd0\xbe\xd0\xb9 \xd1\x81\xd0\xbb\xd1\x83\xd1\x87\xd0\xb0\xd0\xb9\xd0\xbd\xd1\x8b\xd0\xb5 \xd0\xbf\xd0\xb0\xd0\xbf\xd0\xba\xd0\xb8"" /UNILOG:" + logFileName;\n    process.StartInfo.ErrorDialog = false;\n    process.StartInfo.LoadUserProfile = false;\n    process.StartInfo.UseShellExecute = false;\n    process.StartInfo.CreateNoWindow = true;\n    process.StartInfo.WorkingDirectory = @"D:\\temp\\\xd0\xbd\xd0\xb5\xd0\xba\xd0\xbe\xd1\x82\xd0\xbe\xd1\x80\xd1\x8b\xd0\xb5 \xd1\x81\xd0\xbb\xd1\x83\xd1\x87\xd0\xb0\xd0\xb9\xd0\xbd\xd1\x8b\xd0\xb5 \xd0\xbf\xd0\xb0\xd0\xbf\xd0\xba\xd0\xb8";\n    bool processStarted = process.Start();\n\n    if (processStarted)\n    {\n        process.WaitForExit();\n        string output = File.ReadAllText(logFileName);\n        File.Delete(logFileName);\n        // TODO: Do something with the output.\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n