1

I have two console apps written with C#. I'm trying to exchange messages between them. In an attempt to do this, I'm using non-persisted memory-mapped files. In my scenario, one console app is the parent and the other is the child. Sometimes, the parent will send a message to the child. Other times, the child will send a message to the parent.

I can't figure out how to do this though. It's like each process is either listening or speaking. It's not actively doing both. At this time, I'm trying to exchange messages between the two processes using a struct that's defined as this:

public struct Message
{
  public string Source { get; set; }

  public string Text { get; set; }
}

My parent console app has a method that looks like this:

private void SendMessageToChild(string text, int childHandle)
{
  Console.WriteLine("Sending message to child...");

  var messageChannelFileName = childHandle.ToString() + ".msgs";
  using (var messageChannelFile = MemoryMappedFile.CreateOrOpen(messageChannelFileName, 10240))
  {
    using (var memoryMappedAccessor = messageChannelFile.CreateViewAccessor())
    {
      var message = new Message();
      message.Text = text;
      message.Source = "Parent";

      memoryMappedAccessor.Write<Message>(0, ref message);
    }
  }

  Console.ReadKey(); // This is to keep the memory mapped file open for the child to be able to read it
  Console.WriteLine("Successfully sent message to child.");
}

My child console app (process) has a method that looks like this:

private void StartListening()
{
  Task.Run(() =>
  {
    var messageChannelFileName = Process.GetCurrentProcess().Id + ".msgs";
    using (var messageChannelFile = MemoryMappedFile.OpenExisting(messageChannelFileName, MemoryMappedFileRights.Read))
    {
      var message = new Message();
      using (var messageAccessor = messageChannelFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
      {
        messageAccessor.Read<Message>(0, out message);
        Console.WriteLine(message.Text);
      }
    }

    Console.ReadKey();  // This is to keep the memory mapped file
  });
}

This approach isn't working. I never see the message printed to the console window. At the same time, I do not see a way to send messages back-and-forth. In my opinion, the Console.ReadKey required in both sides locks the file.

Am I misunderstanding something? Am I using the wrong thing to exchange messages between two processes? I know I can't use Pipes for my scenario, which is why I went with memory mapped files.

Some User
  • 5,257
  • 13
  • 51
  • 93
  • Have you considered just using sockets? Or why can't this just run under a single application and use threads? It seems like you are really over-complicating the issue. – raterus Oct 24 '18 at 15:21
  • Have you considered using a messaging system/library such as ZeroMQ? See https://blog.scottlogic.com/2015/03/20/ZeroMQ-Quick-Intro.html – Rui Jarimba Oct 24 '18 at 15:21
  • Check out named pipes. There is even an example of what you are trying to do. https://stackoverflow.com/questions/13806153/example-of-named-pipes – Señor CMasMas Oct 24 '18 at 15:23
  • You could pass data using Standard Input and Standard Output between parent and child process instead of using a connection. – jdweng Oct 24 '18 at 15:23
  • are you sure to have same name in parent and child for messageChannelFileName? – Frenchy Oct 24 '18 at 15:59

1 Answers1

0

Its really easy to communicate between 2 processes

For example Parent process do that :

        // create EventWaitHandle, MemoryMapped and accessor
        ewh = new EventWaitHandle(false, EventResetMode.AutoReset, "ewhFreePIE");
        memory = MemoryMappedFile.CreateOrOpen("hookFreePIE", 68, MemoryMappedFileAccess.ReadWrite);
        accessor = memory.CreateViewAccessor();
                    :
                    :
        // Send message with accessor.write                     
        ewh.Set();//say to other process, there is something to read

Example of Child Process:

        memory = MemoryMappedFile.CreateOrOpen("hookFreePIE", 68, MemoryMappedFileAccess.ReadWrite);
        accessor = memory.CreateViewAccessor();
        ewh = EventWaitHandle.OpenExisting("ewhFreePIE");
        :
        :
     // sample of loop   
     public void StartLoop()
    {           
        while (running)
        {
            ewh.WaitOne();// wait Set() of another or same process
            if (cmdtostop) //you could create cmdstop inside memorymapped file (set first byte to 1 for example
            {
                running = false;
            }
            else
            {
                //do something with data , using accessor.Read
        }
    }

if you want child send to parent you create another EventWaithandle and do the same thing from child to Parent

Dont forget to dispose resource when process finish

Frenchy
  • 16,386
  • 3
  • 16
  • 39