zoukankan      html  css  js  c++  java
  • wpf进程间通讯

    在联想智能识别项目中,需要用到进程间通讯,并且是低权限向高权限发送消息。首先声明一下,此项目是wpf的。

    首先先简要说一下什么时候会用到进程间通讯,如:在Windows程序中,各个进程之间如果需要交换数据,此时就可以用到进程通讯。

     先讲讲怎么实现发送消息: 要用进程间通讯,就必须用到参数WM_COPYDATA,此参数的主要目的是允许在进程间传递只读数据。

     发送消息需要用到SendMessage函数,如果接受方未接收完数据的话,是不会返回的,所以发送方在此过程中是不可能删除和修改数据的。

     这个函数如下: 

    [DllImport("User32.dll", EntryPoint = "SendMessage")]
            private static extern int SendMessage(
            IntPtr hWnd,                   //目标窗体句柄
            int Msg,                       //WM_COPYDATA
            int wParam,                //自定义数值
            ref  CopyDataStruct lParam             //传递消息的结构体,
            );

    SendMessage函数用到的数据结构如下:

    [StructLayout(LayoutKind.Sequential)]
            public struct CopyDataStruct
            {
                public IntPtr dwData;//用户定义数据  
                public int cbData;//字符串长度
                [MarshalAs(UnmanagedType.LPStr)]
                public string lpData;//字符串
            }

     该结构用来定义用户要传递的消息的数据

    上面SendMessage的第一个参数需要传递目标窗体的句柄,所以,发送消息前,我们得先找到目标窗体的句柄。 方法如下:

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

    参数:

     lpszClassName       指向一个以null结尾的字符串,指定了窗口类(一个WNDCLASS结构)的名字。如果lpszClassName为NULL,则所有的类名都匹配。

     lpszWindowName   指向一个以null结尾的字符串,指定了窗口的名字(窗口的标题)。如果lpWindowName为NULL,所有的窗口名都匹配。

    我们在找时,可以第一个窗体传Null,第二个传入接受消息的窗体的名称。 找到目标窗体的句柄之后,我们就可以来发送消息了 说完发送消息,再来说说接收消息。 接收消息同样也会用到参数WM_COPYDATA和发送消息用的数据结构CopyDataStruct 。

    接下来在接收消息的窗体中重写OnSourceInitialized方法 用法如下:

    protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
                HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
                if (hwndSource != null)
                {
                    IntPtr handle = hwndSource.Handle;
                    hwndSource.AddHook(new HwndSourceHook(WndProc));
                }
            }
    
    
        IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                if (msg == WM_COPYDATA)
                {
                    CopyDataStruct cds = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));//从发送方接收到的数据结构
                    string param = cds.lpData;//获取发送方传过来的消息
                
                }
             
                return hwnd;
            }

    文章接近尾声了,但如果只用上面的发送消息,接受消息的方法,对于平级的或者高权限向低权限的程序来说可能没问题。但如果是低权限向高权限的程序发送消息,该怎么办呢。其实很简单,在我们接受消息前,先调用一下下面这个方法

    [DllImport("user32")]
      public static extern bool ChangeWindowMessageFilter(uint msg, int flags);

    此方法是用来添加或删除能通过隔离级别的消息,第一个参数就是咱们发送消息用到的WM_COPYDATA,相当于一个标识,第二个参数,可以传入1,相当于Add,使咱们传过来的消息能通过级别隔离,如果传入2的话,是删除,即不让通过。 ChangeWindowMessageFilter还有更多参数,在此用不上,所以不多讲了。

     示例下载

    http://www.cnblogs.com/cssmystyle/archive/2011/10/31/2230033.html

  • 相关阅读:
    [原创]失眠应该顺其自然
    [原创]电饭锅终于煮出有粥油的小米粥了
    [原创]背诵是最好的入静法门
    JSON字符串与JSON对象的区别
    C#注解属性的感想一:
    我对面向对象的理解二:
    我对面向对象的理解一:
    如何理解泛型中的new()约束
    vue关于导航守卫的几种应用场景
    vue3中如何去请求数据
  • 原文地址:https://www.cnblogs.com/tianciliangen/p/5303049.html
Copyright © 2011-2022 走看看