.Net程序间的通讯与控制

搬运自:http://wurang.me/2014/04/24/dotnet-IPC.html

如果有一个需求,用一个程序控制另一个程序,最简单的,比如用程序A打开程序B,这个想必平时都会用到,可以使用Process类及相关的方法。那么再打开B的时候发送一些参数,然后B根据这些参数做出一些反映,这该怎么实现?其实还是用Process。

发送端:


     static void Main(string[] args)
{
Console.WriteLine("请输入接收器路径:");
string path = Console.ReadLine();
Console.WriteLine("请输入接收器启动参数:");
string para = Console.ReadLine();
ProcessStartInfo pi = new ProcessStartInfo();
pi.FileName = @path;
pi.Arguments = para;

try
{
Process.Start(pi);
}
catch
{
Console.WriteLine("找不到接收器或出现错误!");
}
Console.ReadKey();
}

接收端:


        static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("未接到信息!");
}
else
{
foreach (string s in args)
{
Console.WriteLine(s);
}
}

Console.ReadKey();
}

这样我们就可以用程序A启动程序B,根据A传入的参数,程序B做出相应的处理。不过在WPF中,就没法直接用Main中的args参数了。对于WPF,可以用下面的方式处理:

1.在App.xaml 中删除 StartupUri,并添加Startup


<Application x:Class="WpfApplication65.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup" >
<Application.Resources>

</Application.Resources>
</Application>

2.在App.xaml.cs中填写startup的内容


   private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow mw = new MainWindow();
foreach(string s in e.Args)
{
mw.txtShow.Text += s;
}
mw.Show();
}

这样就可以获取传入的参数了。

但是再改一下需求,我们不仅仅通过程序启动的时候传入参数,而是需要给一个已经启动的程序传入参数,那么就需要用进程通信了IPC了。IPC需要用到Windows
API,下面将介绍一下WPF实现进程间的通信。

1.新建数据的结构体类库

新建一个类库,类库内容如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DataStruct
{
[StructLayout(LayoutKind.Sequential)]
public struct DataStruct
{
public IntPtr dwData;
public int cbData; // 字符串长度
[MarshalAs(UnmanagedType.LPStr)]
public string lpData; // 字符串
}
}

2.新建信息帮助类库

新建一个类库,引用上一步的结构体类库,类库内容如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace MessageHelper
{
public class MessageHelper
{
public const int WM_DOWNLOAD_COMPLETED = 0x00AA;
public const int WM_COPYDATA = 0x004A;

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr wnd, int msg, int wP, ref DataStruct.DataStruct cds);
}
}

3.发送端

首先引用前两部的类库

发送有两种方式:

a.通过进程名


  var lstProcess = Process.GetProcessesByName(txtProcess.Text);
if (lstProcess.Length > 0)
{
Process proc = lstProcess[0];
DataStruct.DataStruct cds;
cds.dwData = IntPtr.Zero;
cds.lpData = txtMSG.Text;
cds.cbData = System.Text.Encoding.Default.GetBytes(txtMSG.Text).Length + 1;

int fromWindowHandler = 0;

MessageHelper.MessageHelper.SendMessage(proc.MainWindowHandle, MessageHelper.MessageHelper.WM_COPYDATA, fromWindowHandler, ref cds);
}

注意:使用这种方法,如果窗体的ShowInTaskbar=false,也就是不在任务栏显示的话,那么是没有办法通过MainWindowHandle获取窗口的。

b.通过窗口名


  IntPtr hwnd = MessageHelper.MessageHelper.FindWindow(null, txtTitle.Text);

if (hwnd != IntPtr.Zero)
{
DataStruct.DataStruct cds;
cds.dwData = IntPtr.Zero;
cds.lpData = txtMSG.Text;
cds.cbData = System.Text.Encoding.Default.GetBytes(txtMSG.Text).Length + 1;
// 消息来源窗体
int fromWindowHandler = 0;
MessageHelper.MessageHelper.SendMessage(hwnd, MessageHelper.MessageHelper.WM_COPYDATA, fromWindowHandler, ref cds);
}

注意:使用这种方法,如果有多个窗口的Title是一样的,也是会有冲突的。

4.接收端

首先还是先引用前两步的类库。


 public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Window_Loaded);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
(PresentationSource.FromVisual(this) as HwndSource).AddHook(new HwndSourceHook(this.WndProc));
}

IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{

if (msg == MessageHelper.MessageHelper.WM_COPYDATA)
{

DataStruct.DataStruct cds = (DataStruct.DataStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(DataStruct.DataStruct));

txtShow.Text = cds.lpData;

}

return hwnd;

}

程序下载

.Net程序间的通讯与控制,码迷,mamicode.com

时间: 2024-10-19 23:00:32

.Net程序间的通讯与控制的相关文章

iOS之程序间通讯

程序间通讯 1 设置程序标识,名字自己起, 2 在想要跳转的地儿 加入这行代码就可以 UIApplication sharedApplication] openURL:[NSURL URLWithString:@"ProductTwo:"]]; 例如:one工程程序中:(调用openURL) // // ViewController.m // 程序间通讯OneProduct // // Created by dllo on 16/3/24. // Copyright © 2016年 H

进程间的通讯

进程间通讯机制总结             2013-02-01 17:25:57 分类: LINUX 进程在内核的协调下进行相互间的通讯,主要包括三种方式:信号.管道和套接口三大类. 信号 信号是Unix 系统中的最古老的进程间通讯方式.它们用来向一个或多个进程发送异步事件信号.信号可以从键盘中断中产生,另外进程对虚拟内存的非法存取等系统错误环境下也会有信号产生.信号还被shell 程序用来向其子进程发送任务控制命令. 系统中有一组被详细定义的信号类型,这些信号可以由核心或者系统中其它具有适当

线程间的通讯

直接上一个Demo,模拟生产者和消费者,就是生产了一个物品,然后消费一个物品,就这样你一下,我一下,让他们有类似有通讯的功能一样知道彼此生产了而且消费了.这里需要考虑两个问题面向这个demo时候,第一是线程的安全问题,第二是通讯问题,你一下,我一下 1 package com.thread; 2 // 定义一个共享的数据 3 class User { 4 public String name; 5 public String age; 6 boolean flag = true; // 稍后会用

进程间的通讯(IPC)方式

为什么要进行进程间的通讯(IPC (Inter-process communication)) 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程).资源共享:多个进程之间共享同样的资源.为了作到这一点,需要内核提供锁和同步机制.进程控制:有些进程希望完全控制另一个进程的执行

IOS应用程序间相互跳转 与 传值

阅读本文之前建议参考:<Communicating with Other App程序间通信[翻译]> 在IOS中,实现在app1中打开app2,方法如下: 1,在app2中注册一个URL Schemes 注册的方法很简单,在XXX-info.plist文件中新增一个URL types数组元素,取一个名字,比如"tekuba_net".或者在工程的-TARGETS-Info,中找到URL Types添加一个URL Schemes,名为"tekuba_net"

iOS应用程序间共享数据(转)

我们知道iOS由于沙盒的存在,应用程序不能越过自己的区域去访问别的存储空间的内容,不过可能有许多场景我们需要在应用程序之间共享数据,比如多个应用共用用户名密码进行登录等.虽然我们不能直接通过文件系统来分享数据,不过还是有些方法可以实现,为了方便说明,这里同时创建了两个工程Example1和Example2,实现这两个app之间的信息共享,Example1负责写数据,Example2负责读数据,具体的demo代码可以到这里获取 UIPasteboard 剪贴板是应用程序之间传递数据的简单方式,建议

使用ASP.NET State Server实现多应用程序间共享Session State

原以为ASP.NET State Server原生支持多程序间共享SESSION,以为在同一服务器上 & 同一根域名下部署的多个应用程序间设置了相同了<sessionState/>和<machineKey/>事情就成了! 事实证明是自己TOO YOUNG TOO SIMPLE.根本不WORK! BING了一大轮,再找了一下度娘,看到以下较有参考价值的文章: http://forums.asp.net/t/1759392.aspx?Share+sessions+between

程序间获取ALV显示数据(读取ALV GRID上的数据)

程序间获取ALV数据的两种方法: 方法1:通过修改SUBMIT的目标程序,把内表EXPORT到内存,SUBMIT后IMPORT ,该方法需要修改目标程序,可以任意设置目标程序的中断点: * Execute transaction IA09 to get all Functional Location Tasklists SUBMIT riplko10 WITH SELECTION-TABLE lt_selscreen WITH pn_iflo = abap_true "Select Func L

【转】在Java与C程序间进行socket通信的讨论

1. 背景 使用socket在Java程序与C程序间进行进程间通信.本文主要描述了在同C程序进行通信的Client端的Java实现功能. 1.1. 使用的语言 Client端:Java,JVM(JDK1.3) Server端:C,UNIX(Sun Solaris) 1.2. 讨论范围 数据发送:只涉及到Java中int整型系列的讨论,包括byte,short,int. 数据接受:涉及到byte,short,int,long,float,double,char. 1.3.Java与C的数据类型的比