将对象从一个进程传递到另一个进程

时间:2012-04-09 09:26:55

标签: .net process ipc

我有两个.NET托管程序集。第一个是主要应用程序,一个是独立工具。

现在我要做的是将小工具与主应用程序集成。因此,当用户点击主应用程序中的按钮时,需要将“用户定义的对象”传递给另一个小工具,该工具将运行到另一个不同的独立过程。

但我们只能向进程发送一个字符串参数。

最好的办法是什么?我需要发送到另一个进程的是具有每个文件设置的文件列表。这里的设置是我的“用户定义对象”。

我还有另一个转折点。

如果您的进程未运行,我将首次向其发送参数并运行该进程。 但是如果进程正在运行,我是否可以向其发送参数并将数据附加到现有数据而无需从头再次重新启动它。

有关此方面的任何帮助。如何做到这一点。

由于

4 个答案:

答案 0 :(得分:4)

在最简单的级别,您可以将位置传递给包含序列化对象或其他配置选项的文件(可能在临时区域中)。

更有趣的是,您可以传递一些IPC通道信息 - 可能是一个端口号来连接套接字等 - 并建立您喜欢的任何类型的IPC:远程处理,WCF,原始套接字等等。

答案 1 :(得分:3)

.NET 4支持memory mapped files,这是一种干净,方便且高效的机制,用于在进程之间共享任意数据(当然,您也可以以更低技术的方式执行此操作,例如通过写入临时文件)。

您可以从主进程创建非持久内存映射文件,将用户对象的序列化形式写入其中,然后在子进程内反序列化对象。您需要使对象类可序列化(显然),并将内存映射文件的名称从主进程传递给子进程;但是 name 是一个字符串,因此您可以将其作为命令行参数传递。

MSDN上还有一个example确切地知道如何做到这一点。

答案 2 :(得分:1)

我今天遇到了同样的问题。至少,我用这种方式解决了问题:

使用Newtonsoft.Json.dll,序列化和反序列化对象,并通过WM_COPYDATA消息传递字符串。

在主机应用中:

致电儿童应用:

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

接收消息:

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;
    }
}

反序列化对象:

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

在儿童应用中:

获取主持人句柄:

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

发送序列化字符串:

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; }
}

工作正常!试试吧?

答案 3 :(得分:0)

我找到了两个很好的解决方案来解决上述问题。

1)构造一个以所有给定输入为列的数据表,并将其写为xml。并以该文件作为输入启动进程,并将该xml文件读入调用的进程。 在这个解决方案中,我无法控制我的新进程,我甚至无法调试它。这样做时我发现了很多复杂性。

2)所以找到了这个解决方案,添加exe作为解决方案的引用,只需将文件作为输入调用它作为对程序集的简单调用。现在可以完全控制它。我甚至可以做异常处理。

感谢大家的回复。