C# 从C代码执行的Process.StandardInput或应用程序的编码问题
我对C# 从C代码执行的Process.StandardInput或应用程序的编码问题,c#,.net,encoding,utf-8,process,C#,.net,Encoding,Utf 8,Process,我对进程的编码有问题。标准输入编码。我在Windows窗体应用程序中使用了一些进程,但输入应该是UTF-8Process.StandardInput.Encoding是只读的,因此我无法将其设置为UTF-8,并且它会使用Windows默认编码,这会破坏UTF-8中良好的本机字符。程序中使用两个进程:一个将输出写入文件,另一个读取。因为我可以将输出编码设置为UTF-8,所以该部分工作正常,但回读是我遇到问题的部分。我将包括我使用流程的部分 ProcessStartInfo info = new P
进程的编码有问题。标准输入
编码。我在Windows窗体应用程序中使用了一些进程,但输入应该是UTF-8Process.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();
Console.InputEncoding = Encoding.UTF8;
现在可以工作了。将我的应用程序输出类型设置为console应用程序,并设法在窗体出现之前隐藏console窗口。只有当程序运行时,控制台窗口弹出并隐藏,它才能像正常一样工作
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());
}
}
静态类程序
{
[DllImport(“kernel32.dll”)]
静态外部布尔附件控制台(int dwProcessId);
private const int ATTACH_PARENT_PROCESS=-1;
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部bool SetConsoleCP(
uint wCodePageID
);
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部单元getConsoleP();
[DllImport(“user32.dll”)]
公共静态外部IntPtr FindWindow(字符串lpClassName,字符串lpWindowName);
[DllImport(“user32.dll”)]
静态外部布尔显示窗口(IntPtr hWnd、int nCmdShow);
///
///应用程序的主要入口点。
///
[状态线程]
静态void Main()
{
Console.Title=“Stok”;
//将控制台输出重定向到父进程;
//必须在调用Console.WriteLine()之前
附加控制台(附加父进程);
System.Console.InputEncoding=Encoding.UTF8;
IntPtr hWnd=FindWindow(null,“Stok”);//将控制台窗口标题放在这里
如果(hWnd!=IntPtr.Zero)
{
//把窗户藏起来
ShowWindow(hWnd,0);//0=SW\u隐藏
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(新Form1());
}
}
使用以下一种方式创建的StreamWriter(而不是StandardInput)可获得所需的结果:
StreamWriter utf8Writer = new StreamWriter(proc.StandardInput.BaseStream, Encoding.UTF8);
utf8Writer.Write(...);
utf8Writer.Close();
另一种解决方案是在创建流程之前设置
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();
Console.InputEncoding = Encoding.UTF8;
我刚刚遇到这个问题,无法使用
Console.inpunecoding
技术,因为它似乎只在控制台应用程序中工作
因此,我尝试了Victor的答案,但是我遇到了与评论员MvanGeest相同的问题,其中BOM仍在添加中。过了一会儿,我发现可以创建一个禁用BOM的新UTF8Encoding实例,这样做可以停止编写BOM。下面是Victor示例的修改版本,显示了更改
StreamWriter utf8Writer = new StreamWriter(proc.StandardInput.BaseStream, new UTF8Encoding(false));
utf8Writer.Write(...);
utf8Writer.Close();
希望这能节省一些时间。我在将StandardInput发送到“cmd.exe”时遇到了各种编码问题。我正在生成一个批处理文件,该文件使用mklink和各种非ASCII文件名 我得出的结论是,在UTF8 StreamWriter中包装StandardInput.BaseStream无法正常工作(至少在使用cmd.exe和我拥有的文件名时)。更改编码修复了一些问题,但破坏了其他问题 这就是我的工作原理:
- 将批处理文件以UTF8 no BOM的形式保存到临时文件中,如下所示:file.writealText(“temp.bat”、batchText、新UTF8Encoding(false))李>
- 将StandardOutputEncoding和StandardErrorEncoding设置为Encoding.UTF8
- 发送至标准输入两行:“chcp 65001”+Environment.NewLine+“temp.bat”+Environment.NewLine
忘记标准输入编码吧,发送的两行是ASCII谢谢。很好地解决了这个问题。请注意,它也适用于StandardOutput。不幸的是,这似乎不再有效-UTF16(!)BOM(FF FE)仍在数据之前写入。尼克的解决方案似乎是目前唯一丑陋的解决方案。