C# 進程間通信之二傳遞復雜數據類型(轉)


C#下使用WM_COPYDATA傳輸數據說到Marshal的應用

       筆者曾在一個項目的實施過程中,需要使用WM_COPYDATA在本地機器的兩個進程間傳輸數據。在C++中實現非常簡單,但在C#中實現時卻出現了麻煩。由於沒有指針,使用COPYDATASTRUCT結構傳遞數據時,無法正確傳遞lpData。從網上搜尋文檔,找到一個例子,是將COPYDATASTRUCT結構的lpData聲明為string。這樣雖然能傳遞字符串,但不能傳遞隨意的二進制數據。

       偶然地,我查閱MSDN幫助時,發現了Marshal類。該類概述描述道:提供了一個方法集,這些方法用於分配非托管內存、復制非托管內存塊、將托管類型轉換為非托管類型,此外還提供了在與非托管代碼交互時使用的其他雜項方法。這時,我豁然開朗,覺得找到了一個托管代碼與非托管代碼交互的橋梁。

       於是我聲明COPYDATASTRUCT如下:

       [StructLayout(LayoutKind.Sequential)]

              public struct COPYDATASTRUCT

              {

                     public IntPtr dwData;

                     public int cbData;

                     public IntPtr lpData;

              }

       在發送數據時,我使用Marshal類分配一塊全局內存,並將數據拷入這塊內存,然后發送消息:

       COPYDATASTRUCT cds;

              cds.dwData = (IntPtr)flag;

              cds.cbData = data.Length;

              cds.lpData = Marshal.AllocHGlobal(data.Length);

              Marshal.Copy(data,0,cds.lpData,data.Length);

              SendMessage(WINDOW_HANDLER,WM_COPYDATA,0,ref cds);

在接收數據時,我使用Marshal類將數據從這塊全局內存拷出,然后處理消息:

COPYDATASTRUCT cds = new COPYDATASTRUCT();

    Type mytype = cds.GetType();

              cds = (COPYDATASTRUCT)m.GetLParam(mytype);

              uint flag = (uint)(cds.dwData);

              byte[] bt = new byte[cds.cbData];

       Marshal.Copy(cds.lpData,bt,0,bt.Length);

詳細源碼如下:

/// <summary>

       /// Windows 的COPYDATA消息封裝類。

       /// </summary>

       public class Messager : System.Windows.Forms.Form

       {

              /// <summary>

              /// 必需的設計器變量。

              /// </summary>

              private System.ComponentModel.Container components = null;

 

              //消息標識

              private const int WM_COPYDATA = 0x004A;

              //消息數據類型(typeFlag以上二進制,typeFlag以下字符)

              private const uint typeFlag = 0x8000;

              /// <summary>

              /// 重載CopyDataStruct

              /// </summary>

              [StructLayout(LayoutKind.Sequential)]

              public struct COPYDATASTRUCT

              {

                     public IntPtr dwData;

                     public int cbData;

                     public IntPtr lpData;

              }

              //

              [DllImport("User32.dll",EntryPoint="SendMessage")]

              private static extern int SendMessage(

                     int hWnd,                                  // handle to destination window

                     int Msg,                              // message

                     int wParam,                               // first message parameter

                     ref COPYDATASTRUCT lParam    // second message parameter

                     );

              //

              [DllImport("User32.dll",EntryPoint="FindWindow")]

              private static extern int FindWindow(string lpClassName,string lpWindowName);

 

              //接收到數據委托與事件定義

              public delegate void ReceiveStringEvent(object sender,uint flag,string str);        

              public delegate void ReceiveBytesEvent(object sender,uint flag,byte[] bt);

              public event ReceiveStringEvent OnReceiveString;

              public event ReceiveBytesEvent OnReceiveBytes;

              //發送數據委托與事件定義

              public delegate void SendStringEvent(object sender,uint flag,string str);            

              public delegate void SendBytesEvent(object sender,uint flag,byte[] bt);

              public event SendStringEvent OnSendString;

              public event SendBytesEvent OnSendBytes;

              //

              public Messager()

              {

                     //

                     // Windows 窗體設計器支持所必需的

                     //

                     InitializeComponent();

                     //

                     // TODO: 在 InitializeComponent 調用后添加任何構造函數代碼

                     //

              }

 

              /// <summary>

              /// 清理所有正在使用的資源。

              /// </summary>

              protected override void Dispose( bool disposing )

              {

                     if( disposing )

                     {

                            if(components != null)

                            {

                                   components.Dispose();

                            }

                     }

                     base.Dispose( disposing );

              }

 

              #region Windows 窗體設計器生成的代碼

              /// <summary>

              /// 設計器支持所需的方法 - 不要使用代碼編輯器修改

              /// 此方法的內容。

              /// </summary>

              private void InitializeComponent()

              {

                     //

                     // Messager

                     //

                     this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

                     this.ClientSize = new System.Drawing.Size(200, 14);

                     this.Name = "Messager";

                     this.ShowInTaskbar = false;

                     this.Text = "Demo_Emluator";

                     this.WindowState = System.Windows.Forms.FormWindowState.Minimized;

 

              }

              #endregion          

              /// <summary>

              ///重載窗口消息處理函數

              /// </summary>

              /// <param name="m"></param>

              protected override void DefWndProc(ref System.Windows.Forms.Message m)

              {

                     switch(m.Msg)

                     {

                            //接收CopyData消息,讀取發送過來的數據

                            case WM_COPYDATA:

                                   COPYDATASTRUCT cds = new COPYDATASTRUCT();

                          Type mytype = cds.GetType();

                                   cds = (COPYDATASTRUCT)m.GetLParam(mytype);

                                   uint flag = (uint)(cds.dwData);

                                   byte[] bt = new byte[cds.cbData];

                                   Marshal.Copy(cds.lpData,bt,0,bt.Length);

                                   if(flag <= typeFlag)

                                   {

                                          if(OnReceiveString != null)

                                          {

                                                 OnReceiveString(this,flag,System.Text.Encoding.Default.GetString(bt));

                                          }

                                   }

                                   else

                                   {

                                          if(OnReceiveBytes != null)

                                          {

                                                 OnReceiveBytes(this,flag,bt);

                                          }

                                   }

                                   break;

                            default:

                                   base.DefWndProc(ref m);

                                   break;

                     }

              }

              /// <summary>

              /// 發送字符串格式數據

              /// </summary>

              /// <param name="destWindow">目標窗口標題</param>

              /// <param name="flag">數據標志</param>

              /// <param name="str">數據</param>

              /// <returns></returns>

              public bool SendString(string destWindow,uint flag,string str)

              {

                     if(flag > typeFlag)

                     {

                            MessageBox.Show("要發送的數據不是字符格式");

                            return false;

                     }

                     int WINDOW_HANDLER = FindWindow(null,@destWindow);

                     if(WINDOW_HANDLER == 0) return false;

                     try

                     {

                            byte[] sarr = System.Text.Encoding.Default.GetBytes(str);

                            COPYDATASTRUCT cds;

                            cds.dwData = (IntPtr)flag;

                            cds.cbData = sarr.Length;

                            cds.lpData = Marshal.AllocHGlobal(sarr.Length);

                            Marshal.Copy(sarr,0,cds.lpData,sarr.Length);

                            SendMessage(WINDOW_HANDLER,WM_COPYDATA,0,ref cds);

                            if(OnSendString != null)

                            {

                                   OnSendString(this,flag,str);

                            }

                            return true;

                     }

                     catch(Exception e)

                     {

                            MessageBox.Show(e.Message);

                            return false;

                     }

              }

              /// <summary>

              /// 發送二進制格式數據

              /// </summary>

              /// <param name="destWindow">目標窗口</param>

              /// <param name="flag">數據標志</param>

              /// <param name="data">數據</param>

              /// <returns></returns>

              public bool SendBytes(string destWindow,uint flag,byte[] data)

              {

                     if(flag <= typeFlag)

                     {

                            MessageBox.Show("要發送的數據不是二進制格式");

                            return false;

                     }

                     int WINDOW_HANDLER = FindWindow(null,@destWindow);

                     if(WINDOW_HANDLER == 0) return false;

                     try

                     {

                            COPYDATASTRUCT cds;

                            cds.dwData = (IntPtr)flag;

                            cds.cbData = data.Length;

                            cds.lpData = Marshal.AllocHGlobal(data.Length);

                            Marshal.Copy(data,0,cds.lpData,data.Length);

                            SendMessage(WINDOW_HANDLER,WM_COPYDATA,0,ref cds);

                            if(OnSendBytes != null)

                            {

                                   OnSendBytes(this,flag,data);

                            }

                            return true;

                     }

                     catch(Exception e)

                     {

                            MessageBox.Show(e.Message);

                            return false;

                     }

              }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM