0

I have 2 applications in c# that are talking via windows messages App1: sends a message to App2

string msg=UserName+","+UserAge;

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

int len = sarr.Length;

COPYDATASTRUCT cds;

cds.dwData = (IntPtr)100;

cds.lpData = msg;

cds.cbData = len + 1;

result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);

App2:receives the message from App1

COPYDATASTRUCT sentPara = new COPYDATASTRUCT();
Type mytype = sentPara.GetType();
sentPara = (COPYDATASTRUCT)message.GetLParam(mytype);
string[] parameters = sentPara.lpData.Split(',');

Problem: The username is in Russian and when i receive it in App2 i got question marks"???????", i think it's something in the encoding of byte array but i don't how to solve it

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Sara S.
  • 1,365
  • 1
  • 15
  • 33
  • 4
    You're not *doing* anything with the byte array... – Jon Skeet Mar 19 '13 at 09:56
  • No i send it as it's. I also tried to change Default to UTF8 but i didn't work – Sara S. Mar 19 '13 at 09:57
  • Look at what you're setting `lpData` to - you're setting it to `msg`, not `sarr`. You're only using the byte array to find the length to set. – Jon Skeet Mar 19 '13 at 09:59
  • I'm not sure if it's about the byte array i just guess :) – Sara S. Mar 19 '13 at 09:59
  • 1
    may be if you change `cds.lpData = msg` to `cds.lpData = sarr` , it might work. Change encoding to UTF8 as well btw. – Aamir Mar 19 '13 at 09:59
  • possible duplicate of [C# using SendMessage, problem with WM\_COPYDATA](http://stackoverflow.com/questions/6779731/c-sharp-using-sendmessage-problem-with-wm-copydata) - please note that while the title does not match exactly, the linked post is about problems with sending a string-message with COPYDATA structure, so it matches quite well. – quetzalcoatl Mar 19 '13 at 10:21
  • 1
    Please ignore the 'duplicate flag'. I did not think long enough about the issue, and now I don't know how to cancel it. In the linked post, they use something like `cbdata = str.length+1`. This is obviously wrong for multi-byte encodings, as it would surely cause the data of the message to be truncated. Please stay with your solution. – quetzalcoatl Mar 19 '13 at 10:29

2 Answers2

2

I'd add a line to the second code:

    COPYDATASTRUCT sentPara = new COPYDATASTRUCT();
Type mytype = sentPara.GetType();
sentPara = (COPYDATASTRUCT)message.GetLParam(mytype);
var parametersDecoded = System.Text.Encoding.Default.GetString(sentPara.lpData);
string[] parameters = parametersDecoded.Split(',');
zaitsman
  • 8,984
  • 6
  • 47
  • 79
  • 1
    Sara Saeed I only used Default because this is what you use in your app #1. The encoding has to MATCH between the two. If you need UTF8, replace `System.Text.Encoding.Default.GetString()` with `System.Text.Encoding.UTF8.GetString()`. – zaitsman Mar 20 '13 at 08:36
2

Are your two applications running as two separate processes?

If so, then you cannot sent string directly, because it will contain some internal pointers that will not be valid in the other process's adress space. You don't know what the STRING class contains - it is hidden. Therefore, it MAY contain them, not 'surely contains'.

(Although in C#/.Net it surely contains).

You have started well: you need to pack the contents of that string into an raw byte array, guarantee by yourself that it contains only data and no pointers, and then send the raw array to the second process.

The core of your problem is a wrong P/Invoke definition of COPYDATA structure. The lpVoid should not be of string type, but should be of type byte[] or IntPtr. Once you change its type to byte[], the compiler will immediatelly show you that '=msg' and '.Split' are invalid.

Please note that your current SENDING code contains only a single error: the "data length" you provided is the length of the array (it is correct) but also it passes the 'msg', not the array 'sarr'. After fixing the lpVoid type, just set the field to sarr.

Then, on the RECEIVING side, you will need to get the COPYDATA, get a lpVoid from it, use it as a byte[] and pass it to Encoding.GetString() method - similarly to what zaitsman presented.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107