1. Bjarne Anker
  2. PowerBuilder
  3. Thursday, 25 January 2018 20:09 PM UTC

Hi.

 

Has anyone successfully managed to receive string data sent from a C# application using SendMessage?

We have a small starter program written in C# which is triggered from a website.

This starter program will do some small work and pass a string (perhaps XML) to a running PowerBuilder 2017 application (32-bit).

This is the C# code:

[DllImport("user32.dll", SetLastError = true, EntryPoint = "SendMessageA", CharSet = CharSet.Ansi)]
internal static extern Int32 SendMessageAnsiPtr(IntPtr hWnd, uint Msg, Int32 wParam, IntPtr lParam);

ptr = Marshal.StringToHGlobalAnsi("Hello World");
SendMessageAnsiPtr(proc.MainWindowHandle, 0x429, 11, ptr); //11 is the length of the string hardcoded for testing

Marshal.FreeHGlobal(ptr); //freee the memory to avoid memory leak

This triggers an event in PB mapped to the pbm_custom42 eventhandler.

It receives a pointer to the string, and I've tried this:

string ls_result

ls_result = space(wparam)
ls_Result = String(lParam, "address")
 
Sometimes I get som rubbish, and sometimes Powerbuilder crashes.
 
Am I on the right track?
Is there any other way to "decode" the pointer into a string in PowerBuilder?
Or is there another solution?
 
Regards,
 
Bjarne Anker
Michael Kramer Accepted Answer Pending Moderation
  1. Friday, 26 January 2018 11:15 AM UTC
  2. PowerBuilder
  3. # 1

Hi Bjarne,

String(lParam, "address") is the right way to convert a string pointer into an actual string. You can skip Space(WParam) since that empty string is never used.

ANSI vs. Unicode is a "usual suspect" when integration goes sour. Your C# code calls the ANSI version (SendMessageA) but PB is Unicode internally since PB 10.

HTH  /Michael

Comment
  1. Bjarne Anker
  2. Friday, 26 January 2018 13:38 PM UTC
Hi Michael.



 



I tried these changes to my C# and PB code, but still I sometimes receive rubbish and every now and then PB crashes.



I've been thinking about using the WM_COPYDATA in SendMessage(), but I cannot seem to trap the message in any event i PB.



I've tried to listen to Message.Number = 74 in the "other" (pbm_other) event, but it never fires.



So it looks like we have to use another approach, like the registry.



 



Thanks,



 



Bjarne

  1. Helpful
  1. Michael Kramer
  2. Friday, 26 January 2018 15:13 PM UTC
Hi Bjarne,



The PBM_Custom01 ... PBM_Custom75 are the right events to use. They match WM_User ... (WM_User + 74) where WM_User = 1024 as I recall.



"Sometimes rubbish" worries me. To me it sounds like PB is trying to read from memory outside the PBVM which means it is inherently volatile and unsafe.



 



An idea: Is it possible to create a "dialogue" between the two components?





C# calls SendMessage( ) to notify PB.

PB calls a GetMyGreatData( ) function exposed by your C# component  which returns the string of interest.





If the string is the function's return datatype PB should allocate it in PBVM's realm. Instead, if string is a pass-by-ref parameter, then you need to preallocate in PB before calling the function. This is where Space(wParam) to allocate a string of specific length is important.



 



HTH /Michael



 

  1. Helpful
  1. Bjarne Anker
  2. Monday, 29 January 2018 09:52 AM UTC
Hi Michael.



 



That is a good idea.



However, the application which uses "Sendmessage" is just a small console application, started from a protocol handler located in the registry.



It starts when the user clicks on a link on a webpage (just like with ex. iTunes).



So I don't think I can expose a public function in a console application, but I will try.



 



Regards,



 



Bjarne

  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.