TechSapphire Tuesday, 2024-03-19, 9:18 AM
Site menu
Login form
News
Play Games
  • Deep Freeze
  • Ice Slide
  • Gyroball
  • Fat Fish
  • Bush Royal Rampage
  • Inter process communication using C# without named pipes

    Inter process communication sometimes becomes important. Specially when one has to implement single instance application which can take request at runtime. There are different ways to implement inter process communication. Each options comes with its one limitation and restriction. In this article I have discussed 3 different ways to achieve inter process communication.

    1. Using Web API  or Self hosted web service
    In this technique API is hosted in separate thread. Which can communication with UI or main application using static method exposed. This example is of single instance application, where application check if instance is already running than share parameters with already running instance and close it self.

    Limitation: Need process to run as ADMIN or SYSTEM to host API.

    Program.cs 

    static class Program { [STAThread]
     static void Main() {
     string[] args = Environment.GetCommandLineArgs();
     Process thisProc = Process.GetCurrentProcess();
     // Check how many total processes have the same name as the current one
     if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1) {
     WebRequest req = WebRequest.Create("http://localhost:19002/Communication/AddItem/" + args[1]);
     req.Method = "GET";
     HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
     } else {
    
     var config = new HttpSelfHostConfiguration("http://localhost:19002");
     config.Routes.MapHttpRoute(
     name: "API", routeTemplate: "{Controller}/{action}/{Item}", defaults: new {
     item = RouteParameter.Optional
     });
    
     using(HttpSelfHostServer server = new HttpSelfHostServer(config)) {
     server.OpenAsync().Wait();
     Application.EnableVisualStyles();
     Application.SetCompatibleTextRenderingDefault(false);
     Form1 frm1 = new Form1();
     CommonObjects.objRef = frm1;
     Application.Run(frm1);
     }
     }
     }
    }
    

    CommunicationController.cs

    public class CommunicationController: ApiController
     {
     [HttpGet]
     public string AddItem(string Item)
     {
     CommonObjects.objRef.AddItemMethod(Item);
     return "OK";
     }
     }
     public class CommonObjects
     { 
     public static Form1 objRef;
     }
    

    Form1.cs

     public partial class Form1 : Form
     {
     public Form1()
     {
     InitializeComponent();
     }
     public void AddItemMethod(string ItemName)
     {
     this.BeginInvoke((Action)(() =>
     {
     this.listBox1.Items.Add(ItemName);
     }));
     }
     }
    

    Click to download

    2. Using memory mapped file

    Memory mapped files are very easy to implement. Also helps to create communication between multiple processes using common memory file. Where one process write position is read position of other process on same file. In below lecture both method is implemented in same example.

    Limitation: Need both process to run under same user account. 

    process1,cs

    public partial class Process1 : Form
     {
     public Process1()
     {
     InitializeComponent();
     }
     EventLog eventLog = new EventLog();
    
     MemoryMappedFileCommunicator communicator;
    
     private void btnSend_Click(object sender, EventArgs e)
     {
    
     var data = System.Text.Encoding.UTF8.GetBytes(txtSendMessage.Text);
     communicator.Write(data);
     }
    
     private void Process1_Load(object sender, EventArgs e)
     {
    
    
     communicator = new MemoryMappedFileCommunicator("MemoryMappedShare", 4096);
    
     communicator.ReadPosition = 2000;
     communicator.WritePosition = 0;
     communicator.DataReceived += new EventHandler<MemoryMappedDataReceivedEventArgs>(communicator_DataReceived);
     communicator.StartReader();
    
     if (!EventLog.SourceExists("EventShare"))
     {
     EventLog.CreateEventSource("EventShare", "EventShare");
     }
     eventLog.Source = "EventShare";
     eventLog.EntryWritten += new EntryWrittenEventHandler(LogListner);
     eventLog.EnableRaisingEvents = true;
     //communicator.Dispose();
     //communicator = null;
     }
     private void LogListner(object source, EntryWrittenEventArgs e)
     {
     if (e.Entry.Message.StartsWith("Process2:"))
     {
     BeginInvoke(new Action(() => {
     txtReceiveMessage.Text = e.Entry.Message;
     }));
     }
     }
     private void communicator_DataReceived(object sender, MemoryMappedDataReceivedEventArgs e)
     {
     txtReceiveMessage.Text = System.Text.Encoding.UTF8.GetString(e.Data);
     }
    
     private void button1_Click(object sender, EventArgs e)
     {
     eventLog.WriteEntry("Process1:OPENED", EventLogEntryType.Information);
     }
     }
    

    Process2.cs

    public partial class Process2 : Form
     {
     private MemoryMappedFileCommunicator communicator;
     public Process2()
     {
     InitializeComponent();
     }
     EventLog eventLog = new EventLog();
     private void Process2_Load(object sender, EventArgs e)
     {
     communicator = new MemoryMappedFileCommunicator("MemoryMappedShare", 4096);
    
     // This process reads data that begins in the position 0 and writes starting from the position 2000.
     communicator.ReadPosition = 0;
     communicator.WritePosition = 2000;
    
     // Creates an handler for the event that is raised when data are available in the
     // MemoryMappedFile.
     communicator.DataReceived += new EventHandler<MemoryMappedDataReceivedEventArgs>(communicator_DataReceived);
     communicator.StartReader();
    
     if (!EventLog.SourceExists("EventShare"))
     {
     EventLog.CreateEventSource("EventShare", "EventShare");
     }
     eventLog.Source = "EventShare";
     eventLog.EntryWritten += LogListner;
     eventLog.EnableRaisingEvents = true;
     }
     private void LogListner(object source, EntryWrittenEventArgs e)
     {
     if (e.Entry.Message.StartsWith("Process1:"))
     {
     BeginInvoke(new Action(()=> {
     txtReceiveMessage.Text = e.Entry.Message;
     }));
     
     }
     }
     private void communicator_DataReceived(object sender, MemoryMappedDataReceivedEventArgs e)
     {
     txtReceiveMessage.Text = System.Text.Encoding.UTF8.GetString(e.Data);
     }
    
     private void btnSend_Click(object sender, EventArgs e)
     {
     communicator.Write(txtSendMessage.Text);
     }
    
     private void button1_Click(object sender, EventArgs e)
     {
     eventLog.WriteEntry("Process2:OPENED", EventLogEntryType.Information);
     }
     }
    

     

    3. Using event viewer log

    Using event viewer is best option when processes are running under different user accounts. Also event viewer access should be given to user for use. 

    Limitation: Doesn't work for GUEST user.

    Click to download

    Categories
    Programming [27]
    Tips for programming
    Security [2]
    Security Tips
    Google [1]
    Use google faster then ever you use
    Project [14]
    HTML [2]
    Electronics [0]
    Data Structure [0]
    Database [16]
    SQL SERVER
    SSRS [1]
    Sql Server Reporting Services
    Copyright MyCorp © 2024