1

I'm testing a simple concept where I have a structure called ChatMessage that contains 2 byte arrays (MessageText length 512 and UserName length 32) and a DateTime. I pass string arguments to the ChatMessage constructor and convert them to byte arrays, then set the DateTime. After I construct the object I do this:

ChatMessage chat = new ChatMessage("Message", "Username");
IntPtr m = Marshal.AllocHGlobal(Marshal.SizeOf(chat));
Marshal.StructureToPtr(chat, m, true);
SendMessage(...);
Marshal.FreeHGlobal(m);

Seems like it should be pretty straightforward. Create an instance of the struct, marshal it to unmanaged memory and get the pointer. I'm doing it so I can pass it to another program using Windows Messages. the problem is, whenever it gets to the StructureToPtr() line, it throws an AccessViolationException stating that I "Attempted to read or write protected memory...". I don't know what the heck I'm doing wrong. I know I've done this before but I just can't find the project that I did it in.

I just want to marshal the struct to unmanaged memory and pass a pointer to it to another program, then marshal it to managed memory and read it. The struct definition exists in both projects, so that isn't the issue.

HaLo2FrEeEk
  • 586
  • 7
  • 20
  • 1
    The pointer is only valid in your process, not in the one that you send the message too. VirtualAllocEx + WriteProcessMemory required. You really don't want to write code like this, use a process interop mechanism. – Hans Passant Dec 01 '11 at 22:14
  • What does ChatMessage look like (on both sides) and what does Marshal.SizeOf(chat) return? – 500 - Internal Server Error Dec 01 '11 at 22:15
  • Why are you passing "true" for fDeleteOld parameter. Based on your usage, it seems like you'd want to pass false. But, I'm know sure on that. – Matt Smith Dec 01 '11 at 22:20
  • ChatMessage is the same on both sides. It has a DateTime (readonly, set in the constructor), a byte[512] and a byte[32], a constructor, and an overridden ToString(). I'll look into WM_COPYDATA and the othe methods mentioned and see what I can come up with. I'm not sure what Marshal.SizeOf(chat) returns, I didn't look at it. – HaLo2FrEeEk Dec 05 '11 at 22:54

2 Answers2

4

You are marshalling data from managed to unmanaged code by using StructureToPtr. That does not work cross process as noted above.

What you're looking for is a way to serialize and send "dehydrated" objects over the wire cross-process or cross-machine. Take a look at the MSDN Serialization content. Codeproject also has a good article (http://www.codeproject.com/KB/cs/objserial.aspx) on this.

This should get you started. Of course, if you're looking to transmit this kind of data in high-scale/high-performance scenarios you probably want to look at something like Protocol Buffer for .NET or other modern serialization frameworks.

supermem613
  • 606
  • 4
  • 7
  • I'm not concerned about super high speed /capacity, I just want to get a simple message from one application to another. I'll look into the WM_COPYDATA that others mentioned and also into serializing. Thanks. – HaLo2FrEeEk Dec 05 '11 at 22:51
0

You are sending messages cross-process so you need the system to marshal the data from one virtual address space to the other. The only way to do so with Windows messages is to send the WM_COPYDATA message. If you do that then the system will take care of the cross-process issues. It cannot work with a custom defined message.

But if you are wishing to do any serious amounts of inter-process communication then you should look for a higher level mechanism, as suggested by others.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490