Bei dem String versuchst du einen Pointer zwischen zwei Prozessen auszutauschen, aber jeder Prozess hat seinen eigenen Speicherbereich. Das was in einem Programm auf einen gültigen String zeigt, zeigt im anderen auf irgend etwas - höchstwahrscheinlich Müll. Mit der Ausnahme von WM_COPYDATA kann mit Messages immer nur wParam und lParam, also zwei 32 Bit Integer übergeben werden. Und WM_COPYDATA hat auch so seine eigenen kleinen Eigenheiten.
Nur um's noch mal in den Raum zu werfen:
Named Pipes!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)