Share via


C# Convert console output UTF-8 to display in textbox - special characters problems

Question

Friday, July 5, 2013 5:29 AM

Hello,

I do a project on C#.

I lunch a process in my source code, especially a console command.

startinfo.redirectstandartoutput and input are activated.

I redirect the output in UTF-8 with this line : StartInfo.StandardOutputEncoding = UnicodeEncoding.UTF8;

And then is a problem, I wan't to write the output of the process  on a textbox (or a richtextbox), but the french 'é' or 'è', I mean the french special caracters aren't correctly passing (correctly write on the console, but no after the output).

What can I do to write a console standartoutput with 'é' or 'è' correctly on my textbox (or some other) ?

Thank you on the peoples who can help me.

All replies (9)

Friday, July 12, 2013 2:38 AM ✅Answered

In your code you create a delegate DelegueSortieProcessus, but you never use it.  The right way to avoid the cross-thread error is to create a delegate which represent setting text to the RichTextBox(CallBackTextBox  in my last reply). Then instantiate the delegate and call the Invoke method in the method running in another thread.

You may refer to the following code:

public partial class CheckDiskAppli : Form    {        Process myProcess;        public CheckDiskAppli()        {            InitializeComponent();        }        private void CheckDiskAppli_Load(object sender, EventArgs e)        {            myProcess = new Process();            myProcess.StartInfo.FileName = "XXX.exe";            myProcess.StartInfo.UseShellExecute = false;            myProcess.StartInfo.RedirectStandardOutput = true;            myProcess.StartInfo.CreateNoWindow = true;            myProcess.OutputDataReceived += new DataReceivedEventHandler(Sortie_Console);        }        private void buttonLancer_Click(object sender, EventArgs e)        {            myProcess.Start();            myProcess.BeginOutputReadLine();            myProcess.WaitForExit();        }        void Sortie_Console(object sender, DataReceivedEventArgs e)        {            string receivedMessage = e.Data;            if (!string.IsNullOrEmpty(receivedMessage))            {                //Output the data into the RichTextBox                SetTextToRichTextBox(richTextBoxConsole, receivedMessage);            }            else            {                MessageBox.Show("Rien à afficher !", "Erreur d'affichage", MessageBoxButtons.OK, MessageBoxIcon.Error);            }        }        //Delegate representing the method in which you set text to a RichTextBox        delegate void CallBackRichTextBox(RichTextBox rtf, string text);        //The method in which you set text to a RichTextBox        private void SetTextToRichTextBox(RichTextBox rtf, string text)        {            try            {                if (rtf.InvokeRequired)                {                    CallBackRichTextBox d = new CallBackRichTextBox(SetTextToRichTextBox);                    this.Invoke(d, new object[] { rtf, text });                }                else                {                    rtf.Text = rtf.Text + text;                }            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }        }    }

If you still don't understand, I suggest you read   How to: Make Thread-Safe Calls to Windows Forms Controls. carefully.

The way to report the progress to a ProgressBar is the same. Create a delegate, instantiate it and invoke it. I seems not easy every time you want to communicate with WindowsFormsControls in another thread. So you need to find some other way to resolve this problem. I suggest you use BackgroundWorker.

I hope I've made my self clear.

Caillen
MSDN Community Support | Feedback to us
Develop and promote your apps in Windows Store
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


Monday, July 8, 2013 12:53 PM

Hi foudesoft,

I think the characters('é' or 'è') you input in the console is not encoded in UTF-8, probabaly due to the IME.

To make sure it is not the IME problem, please refer to the following code. If the input string is the same with the output string, the encoding of the input string is OK.

    Console.OutputEncoding = Encoding.UTF8;    Console.Write("Input 'é' or 'è' :");    var st = Console.ReadLine();    Console.WriteLine("Output: {0}", st);

If it doesn't work, please provide me the whole code block you use in your project.

Ensure that the Console.InputEncoding, Console.OutputEncoding and the process.StartInfo.StandardOutputEncoding are the same.

I hope it helps!

Caillen
MSDN Community Support | Feedback to us
Develop and promote your apps in Windows Store
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


Tuesday, July 9, 2013 9:14 AM

Thank you for your answer. I found some other solution, with the fonction getEncoding(); And for the moment, it is working.

I've another problem, I wan't to display the console data in a richtextbox.

If I use the synchrone method, it is working if I read the output with readtoend();

I want to use the asynchrone method, to read the console output line per line, with the readline() method. Can you help me with an example with the method process.BeginOutputReadline() and process.outputDataReceived() ?

Thank you for your help.


Wednesday, July 10, 2013 1:55 AM

Hi foudesoft,
MSDN example demonstrates exactly how to use the BeginOutputReadLine method to realize asynchronous programming.
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx

process.StartInfo.UseShellExecute = false;process.StartInfo.RedirectStandardOutput = true;process.Start();string output = p.StandardOutput.ReadToEnd();process.WaitForExit();

The above code dese the same thing with the following code:

process.StartInfo.UseShellExecute = false;process.StartInfo.RedirectStandardOutput = true;process.OutputDataReceived += new DataReceivedEventHandler(recieve);process.Start();process.BeginOutputReadLine();process.WaitForExit();public void recieve(object e, DataReceivedEventArgs outLine){    System.Console.WriteLine(DateTime.Now + " - " + outLine.Data);}

Caillen
MSDN Community Support | Feedback to us
Develop and promote your apps in Windows Store
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


Wednesday, July 10, 2013 9:50 AM

Hello,

I read the MSDN doc, but I don't understand all, then I posted on this forum.

Thank you for your answer.

If I do the same as you, I have a error from compilator, InvalidOperationException, can't do intra-thread communication.

How can I correct this ?

Thank you.


Thursday, July 11, 2013 2:05 AM

The "receive" method runs asynchronously. It means that the code in this method runs in another thread. The exception occurs when you access to the windows forms controls which are in the main thread. For more details please see How to: Make Thread-Safe Calls to Windows Forms Controls.

To resolve this issue, please call the SetTextToTextBox method as follows:

delegate void CallBackTextBox(TextBox tb, string text);        private void SetTextToTextBox(TextBox tb, string text)        {            try            {                if (tb.InvokeRequired)                {                    CallBackTextBox d = new CallBackTextBox(SetTextToTextBox);                    this.Invoke(d, new object[] { tb, text });                }                else                {                    tb.Text = text;                }            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }        }

For more information in multithreading in Windows Forms, see:

Safe, Simple Multithreading in Windows Forms, Part 1

Safe, Simple Multithreading in Windows Forms, Part 2

Safe, Simple Multithreading in Windows Forms, Part 3

Caillen
MSDN Community Support | Feedback to us
Develop and promote your apps in Windows Store
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


Thursday, July 11, 2013 1:29 PM

Thank you for your answer.

namespace Name1
{
    public partial class CheckDiskAppli : Form
    {
        Process myProcess = new Process();
        public delegate void DelegueSortieProcessus(object sender, DataReceivedEventArgs sortieDonneesConsole);

        public Appli()
        {
            InitializeComponent();
            //myProcess.StartInfo. ...
            myProcess.OutputDataReceived += new DataReceivedEventHandler(Sortie_Console);            //ProcessusCheckDisk.ErrorDataReceived += new DataReceivedEventHandler(Erreur_Console);
        }

        private void buttonLancer_Click(object sender, EventArgs e)
        {
                myProcess.Start();
                myProcess.BeginOutputReadLine();
                //myProcess.BeginErrorReadLine();
                myProcess.WaitForExit();
        }

        private void Sortie_Console(object sender, DataReceivedEventArgs sortieDonneesConsole)
        {
            string contenuConsole;

                if (!string.IsNullOrEmpty(sortieDonneesConsole.Data))
                {
                    contenuConsole = sortieDonneesConsole.Data;
                    richTextBoxConsole.Text += contenuConsole;
                }
                else
                {
                    MessageBox.Show("Rien à afficher !", "Erreur d'affichage", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
        }
        /*
        private void Erreur_Console(object sender, DataReceivedEventArgs sortieErreursConsole)
        {
            string erreursConsole;
            erreursConsole = sortieErreursConsole.Data;
            richTextBoxConsole.Text += erreursConsole;
        }
         */

This code give me an error no thread-safe. I must add an invoke maybe, but I don't know where. Can you help me please ?

I will do the output data of the console (choice between normal output or error) in a richtextbox. I do a fonctional version with a synchronus thread, but I don't want to block my application, and than I want to do the asynchronus method, to read line per line the output of the console in my richtextbox.

In the futur :

I would add a progressbar to show the line read, how can I do this ?

If I have an error, the console can tell me if I would do "y" (yes) or "n" (no), how can I do some dialogue ?

Thank you if you can help me to make compile my program no thread-safe in a first time.


Friday, July 12, 2013 11:56 AM

Hello,

Thank you very much for your example, I understand finally how to operate delegate and invoke.

I adapt your line in my program, but I've a problem : my code are compiles but nothing is going in my richtextbox.

Moreover, if I click on the run "lancer" button, it blocked all my program because it has nothing to display.

Must I create a thread to ascend the console output in my program and can stop the thread with a "cancel"  button ?

Thank you.

If it is easier for you to help me, I can send you my source code, but by private message only.


Tuesday, July 16, 2013 8:35 AM

I close this subject. My problem about accent and the problem with asynchrone read are run.

I create a new topic because I have a graphical problem in windows forms.