如果有一个需求,用一个程序控制另一个程序,最简单的,比如用程序A打开程序B,这个想必平时都会用到,可以使用Process类及相关的方法。那么在打开B的时候发送一些参数,然后B根据这些参数做出一些反映,这该怎么实现?其实还是用Process。
发送端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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(); }
接收端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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
1 2 3 4 5 6 7 8 <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的内容
1 2 3 4 5 6 7 8 9 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.新建数据的结构体类库
新建一个类库,类库内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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.新建信息帮助类库
新建一个类库,引用上一步的结构体类库 ,类库内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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.通过进程名
1 2 3 4 5 6 7 8 9 10 11 12 13 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.通过窗口名
1 2 3 4 5 6 7 8 9 10 11 12 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.接收端
首先还是先引用前两步的类库。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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; }
程序下载