-1

Using this example: https://www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes to create an IPC (Server/Client) to pass messages from one process to another.

It works great when using Windows Forms, but when passing messages to the console - it appends bunch of ????????????????????? at the end of each message.

// This works and outputs the correct message.
PipeMessage.Invoke(stringData);
txtMessage.Text = message;

// Outputting same message to console appends bunch of question marks
Console.WriteLine(stringData);

I need to see the original message clean, without any question marks. Please help.

namespace PipesServerTest
{
    // Delegate for passing received message back to caller
    public delegate void DelegateMessage(string Reply);

    class PipeServer
    {
        public event DelegateMessage PipeMessage;
        string _pipeName;

        public void Listen(string PipeName)
        {
            try
            {
                // Set to class level var so we can re-use in the async callback method
                _pipeName = PipeName;
                // Create the new async pipe 
                NamedPipeServerStream pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

                // Wait for a connection
                pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
            }
            catch (Exception oEX)
            {
                Debug.WriteLine(oEX.Message);
            }
        }

        private void WaitForConnectionCallBack(IAsyncResult iar)
        {
            try
            {
                // Get the pipe
                NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
                // End waiting for the connection
                pipeServer.EndWaitForConnection(iar);

                byte[] buffer = new byte[255];

                // Read the incoming message
                pipeServer.Read(buffer, 0, 255);

                // Convert byte buffer to string
                string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);

                // Pass message back to calling form
                PipeMessage.Invoke(stringData);

                // Kill original sever and create new wait server
                pipeServer.Close();
                pipeServer = null;
                pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

                // Recursively wait for the connection again and again....
                pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
            }
            catch
            {
                return;
            }
        }
    }
}

Form:

namespace PipesServerTest
{
    public partial class Form1 : Form
    {
        public delegate void NewMessageDelegate(string NewMessage);
        private PipeServer _pipeServer;

        public Form1()
        {
            InitializeComponent();
            _pipeServer = new PipeServer();
            _pipeServer.PipeMessage += new DelegateMessage(PipesMessageHandler);
        }

        private void cmdListen_Click(object sender, EventArgs e)
        {
            try
            {
                _pipeServer.Listen("TestPipe");
                txtMessage.Text = "Listening - OK";
                cmdListen.Enabled = false;
            }
            catch (Exception)
            {
                txtMessage.Text = "Error Listening";
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void PipesMessageHandler(string message)
        {
            try
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new NewMessageDelegate(PipesMessageHandler), message);
                }
                else
                {
                    txtMessage.Text = message;
                }
            }
            catch (Exception ex)
            {

                Debug.WriteLine(ex.Message);
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _pipeServer.PipeMessage -= new DelegateMessage(PipesMessageHandler);
            _pipeServer = null;

        }
    }
}

screenshot

Alex G
  • 2,984
  • 9
  • 36
  • 76
  • After `NamedPipeServerStream.Read(...)` you should use the returned value (which you currently don't capture) for further processing, not the size of the buffer. – 500 - Internal Server Error May 20 '20 at 14:58
  • @500-InternalServerError I thought next line takes care of that `string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);` – Alex G May 20 '20 at 15:13
  • No, `buffer.Length` is the size you gave when declaring `buffer` (255), but `Read()` might not be able to get that much from the source - it returns what it actually got as its result. – 500 - Internal Server Error May 20 '20 at 15:20
  • I will never send more than `255`, so this is normal. Please provide an example for "you should use the returned value (which you currently don't capture) for further processing" . – Alex G May 20 '20 at 16:28
  • 1
    Something like `var bytesRead = pipeServer.Read(buffer, 0, 255);` and then `string stringData = Encoding.UTF8.GetString(buffer, 0, bytesRead);`. – 500 - Internal Server Error May 20 '20 at 18:11
  • @500-InternalServerError: This resolved the problem! Wow, but why I was getting question marks instead of some `int` values? – Alex G May 20 '20 at 19:28

2 Answers2

2

Looks like your Console charset encoding is set to ASCII. Set the encoding to UTF-8 using OutputEncoding property:

Console.OutputEncoding = System.Text.Encoding.UTF8;
EylM
  • 5,584
  • 2
  • 14
  • 25
  • This made no difference. Even checking programmatically using `if (stringData == "Test Message - 1") { Console.WriteLine("Got the first message"); }` doesn't work, there is some junk applied after. – Alex G May 20 '20 at 16:25
  • Could you post a screen shot? tnx – EylM May 20 '20 at 16:26
  • Sorry, had nothing to do with charset, it was all `NamedPipeServerStream.Read(...)` issues – Alex G May 20 '20 at 19:29
0

Thanks to @500 - Internal Server Error

Replace this:

pipeServer.Read(buffer, 0, 255);
string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);

with this:

var bytesRead = pipeServer.Read(buffer, 0, 255);
string stringData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Alex G
  • 2,984
  • 9
  • 36
  • 76