title: C# to C++ process with WM_COPYDATA passing struct with strings
body: <p>From a c# program I want to use WM_COPYDATA with SendMessage to communicate with a legacy c++/cli MFC application.</p>
  
  <p>I want to pass a managed struct containing string objects.</p>
  
  <p>I can find the handle to the c++ application for use with SendMessage fine.</p>
  
  <p>The bit I don't know about is how the struct and it's strings can be marshalled and read at the other end. Especially as it contains non-blittables.</p>
  
  <p>Do people think this is feasible?
  I'll continue to work on it, but would apprecite someone who's done this sort of thing telling me if it just isn't going to work.</p>
  
  <p>Here is some demo code if it was a c++/cli program and it's not difficult to get it working.
  However, I'd like this to be in a .Net class library so it can easily be re-used.</p>
  
  <pre><code>//Quick demonstation code only, not correctly styled
  int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
  {               
      struct MessageInfo
      {
          int     nVersion;
          char   szTest[ 10 ];        
      };
  
      MessageInfo sMessageInfo;
  
      sMessageInfo.nVersion = 100;
      strcpy( sMessageInfo.szTest, "TEST");   
  
      COPYDATASTRUCT CDS;
  
      CDS.dwData = 1; //just for test
      CDS.cbData = sizeof( sMessageInfo );
      CDS.lpData = &amp;sMessageInfo;
  
      //find running processes and send them a message
      //can't just search for "MYAPP.exe" as will be called "MYAPP.exe *32" on a 64bit machine
      array&lt;System::Diagnostics::Process^&gt;^allProcesses = System::Diagnostics::Process::GetProcesses();
  
      for each (System::Diagnostics::Process^ targetProcess in allProcesses)
      {        
          if (targetProcess-&gt;ProcessName-&gt;StartsWith("MYAPP", System::StringComparison::OrdinalIgnoreCase))
          {
              HWND handle = static_cast&lt;HWND&gt;(targetProcess-&gt;MainWindowHandle.ToPointer());
  
              BOOL bReturnValue = SendMessage( handle, WM_COPYDATA, (WPARAM)0, (LPARAM)&amp;CDS ) == TRUE;
          }
      }
  
      return 0;
  }
  </code></pre>