title: C# using SendMessage, problem with WM_COPYDATA
body: <p>I've been spending a few days (or more) trying to get this to work.</p>
  
  <p>The application at hand is <code>FTPRush</code>, and I know there is a cmd line application called <code>rush_cmdline.exe</code> which uses <code>SendMessage</code> to send requests to <code>FTPRush</code>.</p>
  
  <p>From debugging the <code>rush_cmdline.exe</code> I can see <code>lParam</code>, <code>wParam</code>, <code>Message</code> and <code>hWnd</code>.</p>
  
  <p>My code is as follows (using SendMessage, not SendMessageW):</p>
  
  <pre><code>[DllImport("User32.dll", EntryPoint = "FindWindow")]
  public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
  [DllImport("USER32.DLL", EntryPoint= "SendMessage")]
  public static extern IntPtr SendMessage(int hWnd, int Msg, int wParam, IntPtr lParam);
  </code></pre>
  
  <p>And I've tried a another specification also:</p>
  
  <pre><code>[DllImport("User32.dll", EntryPoint = "SendMessage")]
  public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
  </code></pre>
  
  <p>The handle (<code>hWnd</code>) is not the problem, as this works:</p>
  
  <pre><code>int ftprush = FindWindow("TfmRush", null);
  ShowWindow(ftprush, 8);
  </code></pre>
  
  <p>Which (I didn't paste the dllimport as it's not important here. Let me know if you wish to see it) brings the window to front. Also, I checked by debugging <code>rush_cmdline.exe</code>. So the handle is the same.</p>
  
  <p>Two attempts which both fail (silently):</p>
  
  <pre><code>public const Int32 WM_COPYDATA = 0x4A;
  string msg = "RushApp.FTP.Login('backup','',0); ";
  // 1
  byte[] array = Encoding.UTF8.GetBytes((string)msg);
  int size = Marshal.SizeOf(array[0]) * array.Length + Marshal.SizeOf(array[0]);
  IntPtr ptr = Marshal.AllocHGlobal(size);
  Marshal.Copy(array, 0, ptr, array.Length);
  Marshal.WriteByte(ptr, size - 1, 0);
  SendMessage(ftprush, WM_COPYDATA, 0, ptr);
  
  // 2
  public struct COPYDATASTRUCT
  {
     public IntPtr dwData;
     public int cbData;
     [MarshalAs(UnmanagedType.LPStr)]
     public string lpData;
  }
  
  COPYDATASTRUCT cds;
  cds.dwData = (IntPtr)100;
  cds.lpData = msg;
  cds.cbData = sarr.Length + 1;
  SendMessage(ftprush, WM_COPYDATA, 0, ref cds);
  </code></pre>
  
  <p>I would expect at least the 2nd solution to work, as it matches up pretty well with this: <a href="http://www.perlmonks.org/index.pl?node_id=668761" rel="noreferrer">perl example</a></p>
  
  <p>Any enlightenment is GREATLY appreciated!</p>
  
  <p>Thanks,</p>
  
  <ul>
  <li>Frank</li>
  </ul>
  
  <p>UPDATE:</p>
  
  <pre><code>string msg = "RushApp.FTP.Login('backup','',0);\0";
  var cds = new COPYDATASTRUCT
  {
              dwData = new IntPtr(3),
              cbData = msg.Length + 1,
              lpData = msg
  };
  IntPtr ftprush = FindWindow("TfmRush", null);
  SendMessage(ftprush, WM_COPYDATA, IntPtr.Zero, ref cds);
  </code></pre>