.NET Forum / Languages / C# / December 2007
Passing String to other Applications with SendMessage,...
|
|
Thread rating:  |
Kerem Gümrükcü - 03 Dec 2007 23:04 GMT Hi,
i want to emulate a (synchronous) BroadCastSystemMessage with EnumWindows and SendMessage. I dont want to use the BroadcastSystemMessage because it needs the SE_TCB_NAME Privilege (you dont have this in normal). So i decided to use the EnumWindows with SendMessage. What i try here is to pass a WM_USER+1111 with LParam and WParam, pointing to strings. But when i try to get the strings at the other end with Marshal.PtrToStringAnsi, the String itself is empty. I dont know what the mistake here is, so a little code:
IntPtr ptrIPAddress = IntPtr.Zero; IntPtr ptrGUID = IntPtr.Zero;
ptrIPAddress = Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.textBoxGGIPAIPAddress.Text)); ptrGUID = Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.guidApplicationGUID.ToString()));
ptrIPAddress = Marshal.StringToHGlobalAnsi(this.textBoxGGIPAIPAddress.Text); ptrGUID = Marshal.StringToHGlobalAnsi(this.guidApplicationGUID.ToString());
//(IntPtr,uint, IntPtr,IntPtr) SendMessage(hWnd, (uint)WindowsMessages.WM_USER + 1111, ptrGUID , ptrIPAddress );
Marshal.FreeHGlobal(ptrIPAddress); Marshal.FreeHGlobal(ptrGUID);
At the other end i try this, but nothing is in there:
protected override void WndProc(ref Message m) { if (m.Msg == (uint) WindowsAPIClass.WindowsMessages.WM_USER + 1111) { String s = Marshal.PtrToStringAnsi(m.LParam); MessageBox.Show(s); } base.WndProc(ref m); }
How to do this? I cant use remoting or stuff like that, because the message should be available for any application running on the System,...it seems that the global memory isnt really global,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Michael C - 03 Dec 2007 23:16 GMT > Hi, > [quoted text clipped - 8 lines] > the String itself is empty. I dont know what the mistake here is, so > a little code: You can't pass a pointer cross process. Each application has it own completely seperate memory space. What is a valid pointer for your app is not a valid pointer for another. You should look at the WM_COPY_DATA message as it will copy your string data cross-process and is quite easy to use.
Michael
Kerem Gümrükcü - 03 Dec 2007 23:29 GMT Hi Michael,
yes i know this but I still tried to find a way. I know the WM_COPYDATA but it would be great if this would be possible with some sort of WM_USER. But since processes are exclusive i think i have to go the WM_COPYDATA way,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Serge Baltic - 04 Dec 2007 14:36 GMT Hello,
> i want to emulate a (synchronous) BroadCastSystemMessage > with EnumWindows and SendMessage. Seems like you're trying to enumate SendMessage(HWND_BROADCAST, …) instead. Why not use it?
(H) Serg
Kerem Gümrükcü - 04 Dec 2007 16:10 GMT Hi Serge,
>Seems like you're trying to enumate SendMessage(HWND_BROADCAST, .) instead. >Why not use it? i need a synchronous way in sending the message. I also could use PostMessage but it does place the message into the messageQ and returns in the same moment. Send Message does not (if you use it with every window handle obtained from EnumWindows and not with HWND_BROADCAST,)...
Thanks anyway,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Mattias Sjögren - 04 Dec 2007 19:51 GMT >ptrIPAddress = >Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.textBoxGGIPAIPAddress.Text)); [quoted text clipped - 3 lines] >ptrIPAddress = Marshal.StringToHGlobalAnsi(this.textBoxGGIPAIPAddress.Text); >ptrGUID = Marshal.StringToHGlobalAnsi(this.guidApplicationGUID.ToString()); By overwriting the pointers you're leaking the memory you first allocated with AllocHGlobal. Those calls seem completely unnecessary.
>How to do this? I cant use remoting or stuff like that, because >the message should be available for any application running on >the System,...it seems that the global memory isnt really global,... If you want real global memory you should look at memory mapped files. But it may be easier to use WM_COPYDATA as Michael suggested.
Mattias
 Signature Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com Please reply only to the newsgroup.
Kerem Gümrükcü - 04 Dec 2007 20:14 GMT Hi Mattias,
>By overwriting the pointers you're leaking the memory you first >allocated with AllocHGlobal. Those calls seem completely unnecessary. Yes, this was the call from a earlier try, i removed it....
>If you want real global memory you should look at memory mapped files. >But it may be easier to use WM_COPYDATA as Michael suggested. Memory mapped files are in my case and also the approach of global available data not that secure since want to make the thing more secure. I use encrypted data that must be transfered,...
Thanks for the reply,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Mattias Sjögren - 04 Dec 2007 21:53 GMT >Memory mapped files are in my case and also the approach of global >available data not that secure since want to make the thing more secure. >I use encrypted data that must be transfered,... Sorry I'm not following. Memory mapped files seems lie a much more secure solution in that case, since you can specify a security descriptor for the file mapping and have complete control over who can read and write from it.
Compare that to broadcasting data with window messages where any message recipient gets to read the data.
Whether or not the data is encrypted is irrelevant to your communication mechanism.
Mattias
 Signature Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com Please reply only to the newsgroup.
Kerem Gümrükcü - 05 Dec 2007 04:04 GMT Hi Mattias,
i solved it another way, but my problem is passing the data between two windows does not work. I get garbage at the other end when passing the data with the WM_COPYDATA Message.
Here is Code:
//structure to pass [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct APP_IP_GUID_INFORMATION { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string ApplicationGUID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string IPAddress; }
[StructLayout(LayoutKind.Sequential)] public struct CopyDataStruct { public int dwData; public int cbData; public IntPtr pData; }
IntPtr ptrAIGI = IntPtr.Zero; IntPtr ptrCDS = IntPtr.Zero; IntPtr hWnd = IntPtr.Zero;
GGIPAWin32APIClass.APP_IP_GUID_INFORMATION aigi; aigi.ApplicationGUID = this.guidApplicationGUID.ToString(); aigi.IPAddress = this.textBoxGGIPAIPAddress.Text;
ptrAIGI = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(GGIPAWin32APIClass.APP_IP_GUID_INFORMATION))); Marshal.StructureToPtr(aigi, ptrAIGI, false);
GGIPAWin32APIClass.CopyDataStruct cds; cds.dwData = this.Handle.ToInt32(); cds.cbData = Marshal.SizeOf(typeof(GGIPAWin32APIClass.APP_IP_GUID_INFORMATION)); cds.pData = ptrAIGI;
ptrCDS = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(GGIPAWin32APIClass.CopyDataStruct))); Marshal.StructureToPtr(cds, ptrCDS, false);
/*...........*/
hWnd = new IntPtr(Convert.ToInt32(ClienthWnd.Key.ToString())); HandleRef hWndRef = new HandleRef(this,hWnd); GGIPAWin32APIClass.SendMessage(hWndRef, (uint)GGIPAWin32APIClass.WindowsMessages.WM_COPYDATA, this.Handle, ptrCDS)
/*...........*/
Marshal.FreeHGlobal(ptrAIGI); Marshal.FreeHGlobal(ptrCDS);
The dwData and cbData at the other end are ok, but the pointer to the data is garbage,...why. Any idea? All pinvoke-functions and data is ASCII or ANSI,...
Thanks in advance,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Michael C - 05 Dec 2007 05:11 GMT > The dwData and cbData at the other end are ok, but the pointer to the data > is garbage,...why. > Any idea? All pinvoke-functions and data is ASCII or ANSI,... The pointer is garbage or what it points to is garbage? Are you sure you're creating the data correctly? Try sending a byte array with a few arbitrary values in it first. Also try using the rtlMoveMemory api to copy your data to a byte array into your app as a test (ie not through SendMessage).
Michael
Kerem Gümrükcü - 05 Dec 2007 05:22 GMT Hi Michael,
when i send the Data with WM_COPYDATA, the receiving application has the right cbData and dwData values send from my application, but pData is nothing else than random application. I dont know whether the mistake lies on the sender or the receiver side, but i think the mistake is on the sender side. I debugged my reciver applications CopyDataStruct with VC++ (receiver is a native app) and also a mannaged app. Bott apps pData is useless. Dont as me why! Except the cbData and dwData nothing males sense.
Any ideas. Do i marshal the data the right way? Are my pinvoke signatures ok?
Data should be TCHAR lpIPAddress[128] and TCHAR lpApplicationGUID[128] at the other end... But its something like "@/!29d)383Rgen%2%4"ß?0". Pointing to "i dont know" data,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Michael C - 05 Dec 2007 05:51 GMT > Hi Michael, > [quoted text clipped - 6 lines] > native app) and also a mannaged app. Bott apps pData is useless. > Dont as me why! Except the cbData and dwData nothing males sense. How do you know it's your pointer that is rubbish? The pointer will be changed from one app to the other. It's possible that the data is incorrect *before* it is sent and the SendMessage is working correctly. Check this first using the 2 suggestion in my previous post.
Michael
Kerem Gümrükcü - 05 Dec 2007 06:23 GMT Hi Michael,
i am desperately looking for a Memory Window in my VStudio 2005 Standard Edition. Did i miss something or do i dont have one there? I dont want to debug it the native way or use some external debugger to have a in-depth look into the pointers memory address. I have a symbol file and i can use some external debugger like Smidgeonsofts PEDebugger or some other *.pdb able debugger.
But this is not the point here. When i do a MessageBox on the Structs Members "IPAddress" and "ApplicationGUID" i get valid Strings displayed. Maybe something is corrupted after Marshal.StructToPtr,...i cant see the memory pointers address, thats the point...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Michael C - 05 Dec 2007 06:38 GMT > Hi Michael, > > i am desperately looking for a Memory Window > in my VStudio 2005 Standard Edition. Did i miss > something or do i dont have one there? Try Ctrl + Alt + M and then push 1. Otherwise it should be on a menu somewhere.
> I dont want > to debug it the native way or use some external > debugger to have a in-depth look into the pointers > memory address. I have a symbol file and i can use > some external debugger like Smidgeonsofts PEDebugger > or some other *.pdb able debugger. My suggestion was to just copy the data to a byte array and have a look at what's in the byte array. If that has what you expect then you are half way there. Although looking at the memory window is probably easier.
The other idea is to create a small amount of arbitrary data (again, use a byte array) and see if that gets copied across ok.
Michael
Kerem Gümrükcü - 05 Dec 2007 15:37 GMT Hi Michael,
i was missing the Memory window and the command you suggested didnt work. So i did a raw debugging with ollydbg and a raw disassembly of the memory and looked at the memory pointing from the CopyDataStruct. Everything was fine, but i made a wrong calculation at the other end receiving the WM_COPYDATA. The size and the offset to the data was wrong, so it was clear the i pointed at random process data. Problem solved,..everybody is happy!
And now i found this, but too late...(sigh)
http://msdn2.microsoft.com/en-us/library/s3aw423e(VS.80).aspx http://msdn2.microsoft.com/en-us/library/9k643651(VS.80).aspx
Will be usefull the next time! Visual Studio: Every Day a new experience,...
Thank you very much,...
Regards
Kerem
 Signature ----------------------- Beste Grüsse / Best regards / Votre bien devoue Kerem Gümrükcü Microsoft Live Space: http://kerem-g.spaces.live.com/ Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "This reply is provided as is, without warranty express or implied."
Serge Baltic - 04 Dec 2007 22:41 GMT Hello,
> How to do this? I cant use remoting or stuff like that, because the > message should be available for any application running on the > System,... What do you mean by “available for any application” — is that about not every application being managed?
There're lots of things intended for communication in the Windows NT OS, still I've made practical use of COM only. That should work equally good for both managed and unmanaged. Putting an object into the Running Objects Table makes it possible to place calls on it from other processes, handling the string marshalling issues automatically for you.
If all you need to transmit are strings, you could take a look at DDE also. That's perfectly suited for the case “broadcast a string message to a number of listeners”, and could be implemented in .NET. For instance, that's the way how Shell opens the second document in the existing application, like a new link in IE, a new document in Word, and so on.
(H) Serge
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|