【问题标题】:Encoding problem of Process.StandardInput or application executed from C# codeProcess.StandardInput 的编码问题或从 C# 代码执行的应用程序
【发布时间】:2011-02-20 18:59:10
【问题描述】:

我遇到了Process.StandartInput 编码的问题。我在我的 Windows 窗体应用程序中使用了一些进程,但输入应该是 UTF-8。 Process.StandardInput.Encoding 是只读的,所以我不能将它设置为 UTF-8,它会获取 Windows 默认编码,这会恶化在 UTF-8 中很好的本机字符。程序中使用了两个进程:一个将输出写入文件,另一个读取。因为我可以将输出编码设置为 UTF-8,所以该部分工作正常,但回读是我遇到问题的部分。我将包括我使用该过程的部分。

ProcessStartInfo info = new ProcessStartInfo("mysql");
info.RedirectStandardInput = true;
info.RedirectStandardOutput = false;
info.Arguments = mysqldumpstring;
info.UseShellExecute = false;
info.CreateNoWindow = true;
Process p1 = new Process();
p1.StartInfo = info;
p1.Start();
string res = file.ReadToEnd();
file.Close();

// where encoding should be Encoding.UTF8;
MessageBox.Show(p1.StandardInput.Encoding.EncodingName); 

p1.StandardInput.WriteLine(res);
p1.Close(); 

【问题讨论】:

    标签: c# .net encoding utf-8 process


    【解决方案1】:

    使用 StreamWriter 创建的下一个方式(而不是 StandardInput)给出了预期的结果:

    StreamWriter utf8Writer = new StreamWriter(proc.StandardInput.BaseStream, Encoding.UTF8);
    utf8Writer.Write(...);
    utf8Writer.Close();
    

    【讨论】:

    • 谢谢。很好地解决了问题。请注意,它也适用于 StandardOutput。
    • 不幸的是,这似乎不再起作用 - UTF16 (!) BOM (FF FE) 仍然写在数据之前。 Nick 的解决方法似乎是目前唯一的、丑陋的解决方案。
    【解决方案2】:

    我刚遇到这个问题,无法使用Console.InputEncoding 技术,因为它似乎只在控制台应用程序中工作。

    因此,我尝试了 Victor 的回答,但是我遇到了与评论者 MvanGeest 相同的问题,其中仍在添加 BOM。过了一会儿,我发现可以创建一个禁用 BOM 的新 UTF8Encoding 实例,这样做会阻止 BOM 被写入。这是 Victor 示例的修改版本,显示了更改。

    StreamWriter utf8Writer = new StreamWriter(proc.StandardInput.BaseStream, new UTF8Encoding(false));
    utf8Writer.Write(...);
    utf8Writer.Close();
    

    希望这可以节省一些时间。

    【讨论】:

      【解决方案3】:

      另一种解决方案是在创建进程之前设置Console.InputEncoding

      Console.InputEncoding = Encoding.UTF8;
      

      【讨论】:

        【解决方案4】:

        现在可以将我的应用程序输出类型设置为控制台应用程序,并设法隐藏控制台窗口出现在表单之前。它基本上只在程序运行时正常工作,控制台窗口弹出和隐藏。

        static class Program
        {
            [DllImport("kernel32.dll")]
            static extern bool AttachConsole(int dwProcessId);
            private const int ATTACH_PARENT_PROCESS = -1;
        
            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern bool SetConsoleCP(
                 uint wCodePageID
                 );
        
            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern uint GetConsoleCP();
        
            [DllImport("user32.dll")]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        
            [DllImport("user32.dll")]
            static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Console.Title = "Stok";
                // redirect console output to parent process;
                // must be before any calls to Console.WriteLine()
                AttachConsole(ATTACH_PARENT_PROCESS);
                System.Console.InputEncoding = Encoding.UTF8;
        
                IntPtr hWnd = FindWindow(null, "Stok"); //put your console window caption here
        
                if (hWnd != IntPtr.Zero)
                {
                    //Hide the window
                    ShowWindow(hWnd, 0); // 0 = SW_HIDE
                }
        
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
        

        【讨论】:

          【解决方案5】:

          在将 StandardInput 发送到“cmd.exe”时,我遇到了各种编码问题。我正在生成一个使用 mklink 和各种非 ASCII 文件名的批处理文件。

          我得出的结论是,将 StandardInput.BaseStream 包装在 UTF8 StreamWriter 中无法正常工作(至少使用 cmd.exe 和我拥有的文件名)。更改编码修复了一些但随后破坏了其他的。

          这对我有用:

          • 将批处理文件保存为 UTF8 无 BOM 的临时文件,如下所示:File.WriteAllText("temp.bat", batchText, new UTF8Encoding(false));
          • 将 StandardOutputEncoding 和 StandardErrorEncoding 设置为 Encoding.UTF8
          • 发送到 StandardInput 2 行:“chcp 65001”+ Environment.NewLine +“temp.bat”+Environment.NewLine

          这仅适用于“cmd.exe”,命令“chcp 65001”告诉它使用 UTF8。

          忘记标准输入编码,发送的 2 行是 ASCII

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-10-20
            • 2017-04-07
            • 1970-01-01
            • 2011-11-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多