zoukankan      html  css  js  c++  java
  • C# 通过copydata实现进程间通信

    最近公司需要实现一个基于copydata进程间通信的功能。原来一直没有接触过Windows的进程通信,这次正好可以学习一下。

    程序是基于Winform的,下面直接上代码。

    公共类:

    public class ImportFromDLL
            {
                public const int WM_COPYDATA = 0x004A;
    
                //启用非托管代码  
                [StructLayout(LayoutKind.Sequential)]
                public struct COPYDATASTRUCT
                {
                    public int dwData;    //not used  
                    public int cbData;    //长度  
                    [MarshalAs(UnmanagedType.LPStr)]
                    public string lpData;
                }
    
                [DllImport("User32.dll")]
                public static extern int SendMessage(
                    IntPtr hWnd,     // handle to destination window   
                    int Msg,         // message  
                    IntPtr wParam,    // first message parameter   
                    ref COPYDATASTRUCT pcd // second message parameter   
                );
    
                [DllImport("User32.dll", EntryPoint = "FindWindow")]
                public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
                [DllImport("Kernel32.dll", EntryPoint = "GetConsoleWindow")]
                public static extern IntPtr GetConsoleWindow();
    
            }

    发送方:

    private void SendMessage()
            {
                //声明变量
                string filepath = @"D:GetMsg.exe";//接收消息程序路径
                string strText= "hello world!";//发送的消息//遍历系统中运行的进程,获取接收消息的进程
                Process[] processes = Process.GetProcesses();
                Process process = null;
                foreach (Process p in processes)
                {
                    try
                    {
                        //这两个进程的某些属性一旦访问就抛出没有权限的异常
                        if (p.ProcessName != "System" && p.ProcessName != "Idle")
                        {
                            if (p.ProcessName == "GetMsg")
                            {
                                process = p;
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
    
                //如果接收消息的进程未运行,则开启程序
                if (process == null)
                {//启动接收消息程序
                    process = System.Diagnostics.Process.Start(filepath);                
                    Thread.Sleep(100);//等待接收消息的程序完全打开,否则消息不能发送成功。
                }
    
                //接收端的窗口句柄  
                IntPtr hwndRecvWindow = process.MainWindowHandle;
    
                //自己的进程句柄
                IntPtr hwndSendWindow = Process.GetCurrentProcess().Handle;
                
                //填充COPYDATA结构
                ImportFromDLL.COPYDATASTRUCT copydata = new ImportFromDLL.COPYDATASTRUCT();
                copydata.cbData = Encoding.Default.GetBytes(strText).Length; //长度 注意不要用strText.Length;  
                copydata.lpData = strText;//内容  
    
                //发送消息
                ImportFromDLL.SendMessage(hwndRecvWindow, ImportFromDLL.WM_COPYDATA, hwndSendWindow, ref copydata);
    
                return;
            }

     接收方:

    protected override void WndProc(ref Message m)
            {
                if (m.Msg == ImportFromDLL.WM_COPYDATA)//根据Message.Msg区分消息类型,ImportFromDLL.WM_COPYDATA为发送方定义的消息类型
                {
                    ImportFromDLL.COPYDATASTRUCT copyData = (ImportFromDLL.COPYDATASTRUCT)m.GetLParam(typeof(ImportFromDLL.COPYDATASTRUCT));//获取数据
                    MessageBox.Show(copyData.lpData);
                }
                base.WndProc(ref m);
            }

    注:

    1、发送方和接收方均可以用C++、JAVA等实现,此处就不再做讨论。

    2、在发送方。判断到接收方尚未开启,就执行打开接收方程序的代码,在打开的同时,使用了线程等待:

    Thread.Sleep(100);//等待接收消息的程序打开,否则消息不能发送成功

    若不想使用线程等待,又想传递消息给接收方,则可以考虑使用以下开启进程的重载方法:

    public static Process Start(string fileName, string arguments);
    public static Process Start(string fileName, string userName, SecureString password, string domain);
    public static Process Start(string fileName, string arguments, string userName, SecureString password, string domain);

    具体使用说明,可参照API文档。

  • 相关阅读:
    ubuntu 构建Xilinx交叉编译环境
    codeSourcery交叉编译环境
    ZYNQ学习之路1. Linux最小系统构建
    静态代码块的执行顺序
    storm maven-shade-plugin
    spring 3.2.7 applicationContext.xml
    ZipUtils
    成员内部类
    jetty jndi数据源
    applicationContext中普通数据源不用jndi数据源
  • 原文地址:https://www.cnblogs.com/ztlsir/p/5830656.html
Copyright © 2011-2022 走看看