Reputation: 453
I have an issue with encoding of Process.StandartInput
encoding. I am using some process in my Windows Form application but input should be UTF-8. Process.StandardInput.Encoding
is read only so I can't set it to UTF-8 and it gets Windows default encoding which deteriorate native characters which are good in UTF-8. Two processes are used in the program: one writes output to a file and other reads. Since I can set up output encoding to UTF-8 that part is working properly but reading back is the part where I am having problems. I'll include the part where I use the process.
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();
Upvotes: 25
Views: 10732
Reputation: 18295
Another solution is to set the Console.InputEncoding
before you create the process.
Console.InputEncoding = new UTF8Encoding(false);
Upvotes: 11
Reputation: 1629
Actually there is a lot better way to do so nowadays. Instead of wrapping into extra writer, you can configure Encoding for original one from the very beginning:
Process.Start(new ProcessStartInfo("mysql")
{
UseShellExecute = false,
RedirectStandardInput = true,
StandardInputEncoding = new UTF8Encoding(false),
});
Also, note that Encoding.UTF8
might emit BOM, so, similarly to default StreamWriter
constructor, it is always a good idea to create new UTF8Encoding(false)
to disable BOM (and you can cache it in static field, similarly to what MS are doing internally)
Also Nick Randell's answer is underestimated, it works indeed (as long as you are fine to have it globally for your process as well). But in "Big Enterprise" this is not very good solution, different teams might get into conflict on what should be by default.
Upvotes: 1
Reputation: 141
I had various encoding problems when sending StandardInput to "cmd.exe". I was generating a batch file that used mklink with various non ASCII filenames.
I came to the conclusion that wrapping StandardInput.BaseStream in a UTF8 StreamWriter does not work properly (at least with cmd.exe and the filenames I had). Changing encoding fixed some but then broke others.
This is what worked for me:
This is only good for "cmd.exe" the command "chcp 65001" tells it to use UTF8.
Forget about StandardInput encoding the 2 lines being sent are ASCII
Upvotes: 2
Reputation: 131
I've just encountered this problem and was unable to use the Console.InputEncoding
technique because it only seems to work in console applications.
Because of this I tried Victor's answer, however I encountered the same issue as the commenter MvanGeest where by the BOM was still being added. After a while I discovered that it is possible to create a new instance of UTF8Encoding that has the BOM disabled, doing this stops the BOM from being written. Here is a modified version of Victor's example showing the change.
StreamWriter utf8Writer = new StreamWriter(proc.StandardInput.BaseStream, new UTF8Encoding(false));
utf8Writer.Write(...);
utf8Writer.Close();
Hope this saves someone some time.
Upvotes: 13
Reputation: 418
Using of StreamWriter created the next way (instead of StandardInput) gives desired result:
StreamWriter utf8Writer = new StreamWriter(proc.StandardInput.BaseStream, Encoding.UTF8);
utf8Writer.Write(...);
utf8Writer.Close();
Upvotes: 27
Reputation: 453
got it working now set my application output type to console application and managed to hide the console window appears before the forms. It basically works like normal only when program run, a console windows pops and hides.
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());
}
}
Upvotes: 2