6

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

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

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

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

我对此有另一个转折。

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

对此有任何帮助。如何做到这一点。

谢谢

4

4 回答 4

5

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

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

于 2012-04-09T09:31:39.967 回答
4

.NET 4 支持内存映射文件,这是一种在进程之间共享任意数据的简洁、方便且非常高效的机制(当然,您也可以通过技术含量更低的方式来实现这一点,例如通过写入临时文件)。

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

MSDN 也有一个关于如何执行此操作的示例。

于 2012-04-09T09:32:02.450 回答
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; }
}

它工作正常!试试看?

于 2017-03-17T06:41:09.010 回答
0

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

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

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

谢谢大家的回复。

于 2012-04-10T05:27:59.320 回答