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

6
我有两个.NET托管程序集。第一个是主应用程序,另一个是独立工具。
现在我需要将小工具与主应用程序集成。因此,当用户从主应用程序单击按钮时,“用户定义对象”需要传递到另一个小工具中,该工具将在另一个不同的独立进程中运行。
但是,我们只能向进程发送单个字符串参数。
最好的方法是什么?我需要发送给另一个进程的是带有每个文件设置的文件列表。这里的设置是我的“用户定义对象”。
我还有另一个要点。
如果您的进程第一次未运行,我将向其发送参数并运行该进程。但是,如果进程正在运行,我可以将参数发送给它并将数据附加到现有数据而无需重新启动它吗?
对此有任何帮助。如何实现这一点。
谢谢
4个回答

5

最简单的方法是将位置传递给一个文件(可能在临时区域),该文件包含序列化对象或其他配置选项。

更有趣的是,您可以传递一些IPC通道信息 - 例如连接套接字的端口号等 - 并建立任何类型的IPC:远程调用、WCF、原始套接字等。


3
另一个选择是使用标准输入 - 如果您的工具被设计为从标准输入读取数据,那么您的主应用程序可以通过重定向子进程(工具)的标准输入来传递序列化信息! - VinayC
@VinayC 说得好,而且更简单 - Marc Gravell

4
.NET 4支持内存映射文件,这是一种干净、方便且非常高效的机制,用于在进程之间共享任意数据(当然,您也可以通过写入临时文件等低技术方式来实现此目的)。
您可以从主进程创建一个非持久化的内存映射文件,将用户对象的序列化形式写入其中,然后在子进程中从中反序列化为对象。您需要使对象类可序列化(显然),并将内存映射文件的名称从主进程传递到子进程;但是名称是一个字符串,因此您可以将其作为命令行参数传递。
MSDN还有一个示例,介绍了如何执行此操作。

是的,我想到了一个解决方案,就是从主进程中将所有所需的内容写入一个文件,并将该文件的参数传递给另一个进程。 - sunder
我的现有解决方案不是在.NET 4中,而是在3.0或3.5中。 - sunder
@sunder:那么为什么这个问题被标记为 c#-4.0 - Jon
@sunder 由于运行时版本(.NET)和语言版本(C#)是分开且大部分无关的,因此在这里没有必要使用任何语言版本标签;在语言版本之间不会有任何区别。 - Marc Gravell

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

在Child App中: 获取主机句柄:
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; }
}

它运行良好!试试吗?


0

我找到了两个好的解决方案来回答上面的问题。

1)构建一个包含所有给定输入列的数据表,并将其写入xml。然后启动一个进程,以该文件作为输入,并将该xml文件读入调用的进程中。 在这个解决方案中,我对我的新进程没有控制权,甚至无法进行调试。我发现在执行此操作时存在很多复杂性。

2)因此,我找到了这个解决方案,将exe作为引用添加到解决方案中,并通过简单调用程序集将其作为输入文件调用。现在我完全掌控了它。我甚至可以进行异常处理。

感谢大家的回复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接