我做一个remotting的通讯测试,让控制台程序和wpf窗体通讯。具体实现的功能如下:
1、wpf获取信息在控制台上显示
2、控制台启动wpf,以及在屏幕前端显示
首先,我们来看项目结构:
共三个项目,它们分工明确,test是控制台和wpf的公共类库,它定义了双方通讯的接口,以及接口的实现:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace test 7 { 8 public interface IOfficeService 9 { 10 void Insert(string stream); 11 } 12 [Serializable] 13 public class OfficeServiceImplement : MarshalByRefObject, IOfficeService 14 { 15 public void Insert(string stream) 16 { 17 Console.WriteLine(stream); 18 } 19 } 20 21 public interface IWPFService 22 { 23 IntPtr GetHandle(); 24 } 25 [Serializable] 26 public class WPFServiceImplement : MarshalByRefObject, IWPFService 27 { 28 public static Func<IntPtr> GetWPFHandle { set; get; } 29 public IntPtr GetHandle() 30 { 31 if (GetWPFHandle != null) 32 { 33 return GetWPFHandle(); 34 } 35 return IntPtr.Zero; 36 } 37 } 38 }
wfaKnowledgeWarehouse 是个控制台项目,用来接收从wpf传回来的消息,并打印到屏幕上:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 using System.Runtime.Remoting.Channels.Http; 7 using System.Runtime.Remoting; 8 using System.Runtime.Remoting.Channels; 9 using System.Runtime.Serialization.Formatters; 10 using System.Net.Sockets; 11 using System.Net; 12 using test; 13 using System.Diagnostics; 14 using System.Threading; 15 16 namespace wfaKnowledgeWarehouse 17 { 18 class Program 19 { 20 public const string CHANNEL_NAME = "ConsoleService"; 21 public const string OBJECT_URI = "ConsoleService.rem"; 22 23 /// <summary> 24 /// 二进制信道处理 25 /// </summary> 26 public static SoapServerFormatterSinkProvider Provider = new SoapServerFormatterSinkProvider() 27 { 28 TypeFilterLevel = TypeFilterLevel.Full 29 }; 30 31 static void Main(string[] args) 32 { 33 34 //定义一组服务 35 var channel = new HttpServerChannel(CHANNEL_NAME, 8022, Provider); 36 RemotingConfiguration.RegisterWellKnownServiceType(typeof(OfficeServiceImplement), OBJECT_URI, WellKnownObjectMode.Singleton); 37 38 var consoleInfo = Console.ReadKey(); 39 40 if (consoleInfo.Key == ConsoleKey.A) 41 { 42 //如果按下A,获取wpf窗体句柄 43 44 var ServiceUrl = "http://" + IPAddress.Loopback.ToString() + ":{0}/WPFService.rem"; 45 var WpfService = Activator.GetObject(typeof(IWPFService), string.Format(ServiceUrl, 8023)) as IWPFService; 46 47 try 48 { 49 //启动客户端 50 ProcessStartInfo info = new ProcessStartInfo(); 51 info.FileName = @"D:myworkWordAddInTest2010WpfTestWpfTestinDebugWpfTest.exe"; 52 info.Arguments = ""; 53 info.WindowStyle = ProcessWindowStyle.Minimized; 54 Process pro = Process.Start(info); 55 56 Thread.Sleep(3000); 57 58 var window= WpfService.GetHandle(); 59 60 Console.WriteLine(window.ToInt32()); 61 62 if (Win32APIs.IsIconic(window) != IntPtr.Zero) 63 { 64 Win32APIs.ShowWindow(window, Win32APIs.WindowState.SW_SHOWNOACTIVATE); 65 } 66 67 Win32APIs.SetForegroundWindow(window); 68 69 } 70 catch (Exception ex) 71 { 72 Console.WriteLine(ex); 73 } 74 } 75 Console.Read(); 76 } 77 } 78 }
WpfTest 是wpf项目:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 using System.Net; 15 using test; 16 using System.Windows.Interop; 17 using System.Runtime.Remoting.Channels; 18 using System.Runtime.Remoting.Channels.Http; 19 using System.Runtime.Remoting; 20 using System.Runtime.Serialization.Formatters; 21 using System.Threading; 22 using System.Windows.Threading; 23 24 namespace WpfTest 25 { 26 /// <summary> 27 /// MainWindow.xaml 的交互逻辑 28 /// </summary> 29 public partial class MainWindow : Window 30 { 31 public const string CHANNEL_NAME = "WPFService"; 32 public const string OBJECT_URI = "WPFService.rem"; 33 34 /// <summary> 35 /// 二进制信道处理 36 /// </summary> 37 public static SoapServerFormatterSinkProvider Provider = new SoapServerFormatterSinkProvider() 38 { 39 TypeFilterLevel = TypeFilterLevel.Full 40 }; 41 42 public MainWindow() 43 { 44 InitializeComponent(); 45 } 46 47 public static IntPtr WindowPtr { set; get; } 48 49 private void Button_Click(object sender, RoutedEventArgs e) 50 { 51 var ServiceUrl = "http://" + IPAddress.Loopback.ToString() + ":{0}/ConsoleService.rem"; 52 var WordService = Activator.GetObject(typeof(IOfficeService), string.Format(ServiceUrl, 8022)) as IOfficeService; 53 54 try 55 { 56 WordService.Insert("wbq"); 57 } 58 catch (Exception ex) 59 { 60 MessageBox.Show(ex.Message); 61 } 62 } 63 64 public IntPtr GetHandle() 65 { 66 return WindowPtr; 67 } 68 69 private void Window_Loaded(object sender, RoutedEventArgs e) 70 { 71 WindowPtr = new WindowInteropHelper(this).Handle; 72 var channel = new HttpServerChannel(CHANNEL_NAME, 8023, Provider); 73 RemotingConfiguration.RegisterWellKnownServiceType(typeof(WPFServiceImplement), OBJECT_URI, WellKnownObjectMode.Singleton); 74 WPFServiceImplement.GetWPFHandle = GetHandle; 75 } 76 } 77 }
wpf项目定义了提供了WPFService服务,同时它又使用控制台提供的ConsoleService服务。
小结:想想,我们程序员为老板,为公司提供了一定的技术服务,同时得到一些报酬;老板和公司得到一些技术服务的同时,给程序员付一定的报酬。要和这个社会打交道,大抵如此吧。