Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pass object from one process to another

Tags:

.net

process

ipc

I have two .NET managed assemblies. The first one is main application, and the one is an independent tool.

Now what I have to do is integrate the small tool with main application. So when user click on a button from main application the “User defined object” need to be passed to another small tool which will run into another different independent process.

But we can send only a single string argument only to a process.

What can be best approach to do this? What I need to send to another process is list of files with the settings for each file. Here setting is my “User defined object”.

I have another twist to this.

First time if you process is not running I will send parameter to it and run the process. But if process is running, can I send parameter to it and append the data to existing one without restarting it again from scratch.

Any help regarding that. How this can be done.

Thanks

like image 538
sunder Avatar asked Apr 09 '12 09:04

sunder


3 Answers

At the simplest level, you could pass a location to a file (perhaps in the temp area) containing a serialized object or some other configuration options.

More interestingly, you could pass some IPC channel information - maybe a port number to connect with a socket, etc - and establish any kind of IPC you like: remoting, WCF, raw sockets, whatever.

like image 95
Marc Gravell Avatar answered Nov 04 '22 22:11

Marc Gravell


.NET 4 supports memory mapped files, which is a clean, convenient and very performant mechanism for sharing arbitrary data between processes (of course you can also do this in a much more low-tech way, e.g. by writing to a temporary file).

You can create a non-persisted memory mapped file from your main process, write the serialized form of your user object to it and then deserialize it an object from within the child process. You will need to make the object class serializable (obviously) and also pass the name of the memory-mapped file from the main process to the child; however the name is a string so you can pass it as a command-line argument.

MSDN also has an example on exactly how to do this.

like image 4
Jon Avatar answered Nov 04 '22 23:11

Jon


I had experienced the same problem today. At least, I solved the problem use this way:

Use Newtonsoft.Json.dll, serialize and deserialize the object, and pass string through WM_COPYDATA message.

In host App:

Call child app:

private void RunChild()
{
    string appPath = Path.GetDirectoryName(Application.ExecutablePath);
    string childPath = Path.Combine(appPath, "ChildApp.exe");
    Process.Start(childPath, this.Handle.ToString());
}

Receive message:

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    switch (m.Msg)
    {
        case WM_COPYDATA:
            COPYDATASTRUCT copyData = new COPYDATASTRUCT();
            Type type = copyData.GetType();
            copyData = (COPYDATASTRUCT)m.GetLParam(type);
            string data = copyData.lpData;
            RestorePerson(data);
            break;
    }
}

Deserialize the object:

private void RestorePerson(string data)
{
    var p = JsonConvert.DeserializeObject<Person>(data);
    txtName.Text = p.Name;
    txtAge.Text = p.Age.ToString();
}

In Child App:

Get the host handle:

public ChildForm(string[] args)
{
    InitializeComponent();
    if (args.Length != 0)
        this.hostHandle = (IntPtr)int.Parse(args[0]);
}

Send serialized string:

private void btnSubmit_Click(object sender, EventArgs e)
{
    this.person.Name = txtName.Text;
    this.person.Age = int.Parse(txtAge.Text);

    if (this.hostHandle != IntPtr.Zero)
    {
        string data = JsonConvert.SerializeObject(this.person);
        COPYDATASTRUCT cds = new COPYDATASTRUCT();
        cds.dwData = (IntPtr)901;
        cds.cbData = data.Length + 1;
        cds.lpData = data;
        SendMessage(this.hostHandle, WM_COPYDATA, 0, ref cds);
    }
}

//class Person can used by HostApp by add refrence.
[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

It works fine! try it?

like image 1
liu jw Avatar answered Nov 04 '22 22:11

liu jw