Process.StandardInput或从C#代码执行的应用程序的编码问题

问题描述 投票:17回答:5

我对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
5个回答
23
投票

使用以另一种方式创建的StreamWriter(而不是StandardInput)提供所需的结果:

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

8
投票

我刚遇到此问题,无法使用Console.InputEncoding技术,因为它似乎仅在控制台应用程序中有效。

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

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

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


6
投票

另一种解决方案是在创建进程之前设置控制台InputEncoding。

Console.InputEncoding = Encoding.UTF8;

1
投票

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

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());
    }
}

0
投票

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

我得出结论,将StandardInput.BaseStream封装在UTF8 StreamWriter中不能正常工作(至少使用cmd.exe和我拥有的文件名)。更改编码可以修复某些问题,但后来破坏了其他问题。

这对我有用:

  • 将批处理文件作为UTF8 no 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。

忘记StandardInput编码,发送的两行是ASCII

© www.soinside.com 2019 - 2024. All rights reserved.