I have 2 application and contractor
the contractor
namespace EventAppShellContractor
{
[ComVisible(true)]
public interface IEventAppShell
{
bool IsRunning { get; }
void Run();
void Stop();
event EventHandler<byte[]> Scanned;
}
}
Applition 1 - the shell application This application only communication with some device ro get results
[ComVisible(true)]
public partial class Form1 : Form, IEventAppShell
{
public Form1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)AppShellEventMessage.WM_GET_HANDLER)
{
var result = (IntPtr)Marshal.GetComInterfaceForObject(this, typeof(IEventAppShell));
m.Result = result;
return;
}
base.WndProc(ref m);
}
public event EventHandler<byte[]> Scanned;
public bool IsRunning => true;
public void Run()
{
try
{
var device = new SomeNewDeviceComm();
device.Init();
device.OnScanned = async (s, data) =>
{
Scanned?.Invoke(this, data);
};
device.Start();
}
catch (Exception ex)
{
throw;
}
}
public void Stop()
{
//Close device
device?.Close();
Application.Exit();
}
}
in the paretn application when I need to run the device I'm calling this method:
public class EventAppShellRunner {
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private IEventAppShell m_Device;
private Process m_Process
public void StartDevice(){
m_Process = new Process();
m_Process.EnableRaisingEvents= true;
m_Process.StartInfo.FileName = [EXE file of 1st applcation];
m_Process.Start();
m_Process.WaitForInputIdle();
var mainFormHandle = FindWindow(null, "Form1"); //Receive Uint not zero
IntPtr result = SendMessage(mainFormHandle, (uint)AppShellEventMessage.WM_GET_HANDLER, IntPtr.Zero, IntPtr.Zero);
//Result is Zero for some reason
m_Device= (IEventAppShell)Marshal.GetObjectForNativeVariant(result);
m_Device.Scanned = SomeScanResultHandler...
//in the 'm_Device` I get exption because result is zero
m_Device.Run();
}
public void Stop(){
m_Device?.Stop();
}
}
Is there a way to communicate directly to the 1st application
I tried named pipe and it didn't work well
CodePudding user response:
If the goal is to get two applications to communicate, my approach would be to setup some type of server or message queue to send serialized messages between the applications.
While this might sound complicated, most of the complicated parts are handled by libraries. I managed to setup a simple message transfer using MQTT in about an hour by following this guide. The important part here is that you can send messages, and use standard serialization libraries, like json or protobuf, to generate messages from objects. Many Lower level techniques only provide an "stream of bytes", so you need to handle things like message framing yourself.
Note that I'm not advocating for MQTT specifically, it is just one library I have used. There are many to chose from, rabbitMQ, NetMQ, MQTT, http, gRPC, and many more.
CodePudding user response:
Simple and universal - use TCP socket (localhost).