2010-12-02 18 views
2

私は2つのmdiアプリケーションを持ち、どちらも同じデータベースからデータを取得します。 2つのアプリケーションは、同期を維持するために互いにメッセージを送信できる必要があります。 前後に渡されるメッセージには、受信したアプリケーションに、データベース内のどのデータを見るべきかを伝える文字列(ジョブ番号と追加の関連情報)のみが含まれています。 両方のアプリケーションにメッセージハンドラがあり、各プログラムの起動時にインスタンス化されます。C#とVB6のmdiアプリケーション間のメッセージングinterop

メッセージがVB6アプリケーションからc#アプリケーションに送信されると、メッセージが表示され、適切に動作しますが、C#アプリケーションからVB6アプリケーションに同じタイプのメッセージを送信すると、メッセージが表示されるようですそれをアンパックすると、データの一部しか表示されず、メッセージが無視されます。

私はC#の端で何かを間違ってフォーマットするかもしれないと思っています。私は名前付きパイプに見て推薦する

namespace InterProcessMessaging 
{ 
[StructLayout(LayoutKind.Sequential)] 
    public struct COPYDATASTRUCT 
    { 
     public IntPtr dwData;//a pointer to a number use this to identify your message 
     public IntPtr lpData;//a pointer to the address of the data 
     public IntPtr cbData;//a pointer to the number of bytes to be transferred 

    } 
public class clsMessaging : System.Windows.Forms.NativeWindow, IDisposable 
{ 
//API function to send async. message to target application 
     [DllImport("user32.dll", CharSet = CharSet.Ansi)] 
     public static extern IntPtr SendMessageA(IntPtr hwnd, Int32 wMsg, Int32 wParam, COPYDATASTRUCT lParam); 

    public void SendMessageToVB6(string sendMsg, string WindowsAppTitle) 
    { 
      try 
      { 

       IntPtr hwndTarget = FindWindow(null, WindowsAppTitle); 

       IntPtr pDWData = Marshal.AllocHGlobal(sizeof(Int32));//a pointer to a number used this to identify your message 
       Marshal.StructureToPtr(3, pDWData, true);//place the value 3 at this location 

       IntPtr pLPData = Marshal.StringToHGlobalAnsi(sendMsg.Trim());//a pointer to the address of the data 

       IntPtr pCBData = Marshal.AllocHGlobal(sizeof(Int32));//a pointer to the number of bytes to be transferred 
       Marshal.StructureToPtr(sendMsg.Trim().Length+1, pCBData, true);//place the size of the string at this location 

       COPYDATASTRUCT cds;//a structure containing the three pointers above 
       cds.dwData = pDWData;//a pointer to a number used this to identify your message (3) 
       cds.lpData = pLPData;//a pointer to the address of the data 
       cds.cbData = pCBData;//a pointer to the number of bytes to be transferred 

       if (!System.IntPtr.Zero.Equals(hwndTarget)) 
       { 
        SendMessageA(hwndTarget, 74, 0, cds); 
       } 
      } 
      catch (Exception ex) 
      { 
       Debug.Print(ex.InnerException.ToString()); 
      } 
    } 
} 
} 

答えて

1

これは動作します。このソリューションの

public struct COPYDATASTRUCT 
{ 
    public IntPtr dwData; 
    public UInt32 cbData; 
    [MarshalAs(UnmanagedType.LPStr)] 
    public string lpData; 
} 

[DllImport("User32.dll", EntryPoint = "SendMessage")] 
     public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam); 

IntPtr result; 

      byte[] sarr = System.Text.Encoding.Default.GetBytes(sendMsg); 
      int len = sarr.Length; 
      COPYDATASTRUCT cds; 

      cds.dwData = (IntPtr)3; 
      cds.lpData = sendMsg; 
      cds.cbData = (UInt32)len + 1; 
      result = SendMessage(hwndTarget, WM_COPYDATA, 0, ref cds); 

クレジットはまだメンバーではありませんジム・ケンプ...に行きます。 ありがとうジム!

1

: はここにメッセージを送信する方法です。 .NETでは、この目的でSystem.IO.Pipesを使用できます。 VB6ではWin32APIで簡単に実装できます。名前付きパイプは、WindowsメッセージングよりもIPCを作成するための良い方法です。また、SendMessage経由のIPCではVistaとWin7に制限があります。

+0

を、私は同意すると、ローカルに同様の提案がありました。これのほとんどは継承されています。 –

+0

Windows 7のメッセージングの限界についてもう少し詳しく説明できるのだろうかと思います。レガシーアプリケーションがWindows 7 - 64ビット環境に移行したときに、この状況が発生しました。この時点で私がしようとしていることは、それを取り替えるために時間を取ることができるように、おそらくWebベースのアプリケーションとして機能させることです。 –

+0

セキュリティ上の制限があります。私はVistaのアプリケーション間でのメッセージングの問題に直面しました。 Vistaでは(そしてWin7と思うが)、下位のアプリケーションから上位にメッセージを送信する方法がないようだ。しかし、名前付きパイプの場合はこれを行うことができます。 – DReJ

1

あなたはかなり間違っています。 COPYDATASTRUCT.lpDataのみがポインターです。 dwDataはメッセージ番号を示します。独自のものを選んだ場合は、0を使用します。 cbDataは、ポイント先のデータのサイズです。

さらに問題が発生すると、メモリがリークしています。割り当てたメモリー量が、渡したサイズと一致しません。文字列の変換は損失が多く、string.Length()と同じバイト数を生成しないことがあります。 FindWindowは信頼できないことが知られています。このためにソケットまたは名前付きパイプを使用すると、名前を推測する必要がなくなり、WCFが最適です。

  COPYDATASTRUCT cds; 
      cds.dwData = (IntPtr)3; 
      cds.lpData = Marshal.StringToHGlobalUni(sendMsg); 
      cds.cbData = 2 * (sendMsg.Length + 1); 
      SendMessageA(hwndTarget, 74, 0, cds); 
      Marshal.FreeHGlobal(cds.lpData); 
+0

すべての良いアイデア、ありがとう。上記のようにコードを変更すると、vb6アプリケーションでメッセージハンドラがトリガされないようです。 –

+0

メッセージが送信されないようにスニペットで行ったことはありませんでした。デバッガを使用します。 –

関連する問題