Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Need help with communicating between scripts



  • Please log in to reply
7 replies to this topic
DanHunter
  • Members
  • 13 posts
  • Last active: May 17 2013 07:05 AM
  • Joined: 06 Apr 2013

I modified the final OnMessage() example (using sender.ahk and receiver.ahk) on the sender side by changing the 1st seven lines and the SendMessage Line from this:

TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey

#space::  ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  ; User pressed the Cancel button.
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)

  ****** Same *****



Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    ****** Same *****

    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%  ; 0x4a is WM_COPYDATA. Must use Send not Post.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}

to this:

global PID:=

#space::  ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  ; User pressed the Cancel button.
    return

target:="Receiver.exe"
Process, Exist, %target%
if ErrorLevel=0
{
    Run, %target%,,, PID
    tooltip, launched PID %PID%
} else
    PID:=ErrorLevel
        
result := Send_WM_COPYDATA(StringToSend, PID)

if result = FAIL
    MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
    MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return

;Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
Send_WM_COPYDATA(ByRef StringToSend, PID)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)  ; Set up the structure's memory area.
    ; First set the structure's cbData member to the size of the string, including its zero terminator:
    SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
    NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)  ; OS requires that this be done.
    NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)  ; Set lpData to point to the string itself.
	
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, ahk_pid %PID%  ; 0x4a is WM_COPYDATA. Must use Send not Post.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}

This is because I want to run the receiver as an EXE.

 

So, in my version, the data is received only the first time. Subsequent sends are apparanetly not receivedas there is no return code. Why is this and what is the correct way to use SendMessage to pass a data string to another EXE process?

 

In case it's relevent my OS is win7 Ultimate, 64-bit. Also, the resource monitor displays the receiver PID as active - both for the 1st text data that succeeds and the subsequent text data that all fail.
 



Guest10
  • Members
  • 1216 posts
  • Last active: Oct 30 2015 05:12 PM
  • Joined: 27 Oct 2012

can your script be run as an stand-alone script/example as is?



DanHunter
  • Members
  • 13 posts
  • Last active: May 17 2013 07:05 AM
  • Joined: 06 Apr 2013

My script is not one, but 2 separate scripts. copied from the example for the OnMessage() command (which works perfectly as is, but only on uncompiled scripts).

 

I altered a few lines to make it work on compiled scripts. Now it works perfectly sending the 1st string and never works again, unless I remove the receiver exe from memopry and re-launch it, (which then will again only be good for one message).

 

So it can't be run as an example, because it fails.



noname
  • Members
  • 650 posts
  • Last active:
  • Joined: 12 Nov 2011
✓  Best Answer

Solved a similar problem when using an exe and onmessage by using a "dummy" window so i could send the message using the TargetScriptTitle set to the name of the "dummy" Gui.

 

TargetScriptTitle=onmessagereceive

 

 

That way it worked when creating an exe. ( i used ahk_l unicode  32bit )

 

 

example:

; Example: Send a string of any length from one script to another.  This is a working example.
; To use it, save and run both of the following scripts then press Win+Space to show an
; InputBox that will prompt you to type in a string.

; Save the following script as "Receiver.ahk" then launch it:
#SingleInstance
gui,add,edit,w300 
Gui, show,x-1000,onmessagereceive

OnMessage(0x4a, "Receive_WM_COPYDATA")  ; 0x4a is WM_COPYDATA
return

Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 2*A_PtrSize)  ; Retrieves the CopyDataStruct's lpData member.
    CopyOfData := StrGet(StringAddress)  ; Copy the string out of the structure.
    ; Show it with ToolTip vs. MsgBox so we can return in a timely fashion:
    ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData%
    return true  ; Returning 1 (true) is the traditional way to acknowledge this message.
}
TargetScriptTitle=onmessagereceive

return



#space::  ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  ; User pressed the Cancel button.
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
    MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
    MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return

Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)  ; Set up the structure's memory area.
    ; First set the structure's cbData member to the size of the string, including its zero terminator:
    SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
    NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)  ; OS requires that this be done.
    NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)  ; Set lpData to point to the string itself.
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%  ; 0x4a is WM_COPYDATA. Must use Send not Post.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}

winXP  and ahk unicode


DanHunter
  • Members
  • 13 posts
  • Last active: May 17 2013 07:05 AM
  • Joined: 06 Apr 2013

Aesthetically ugly, but brilliant! Problem solved; thank you!



noname
  • Members
  • 650 posts
  • Last active:
  • Joined: 12 Nov 2011

Aesthetically ugly

 

 

 

True tongue.png

 

So i looked for the minimum code to create a "dummy".Using ahk_l unicode 32bit i ended up like this.

gui,new,,onmessagereceive

return


f4::
detecthiddenwindows on
IfWinExist, onmessagereceive
SoundBeep, 

WinGetPos, x,y,w,h,onmessagereceive
msgbox %x%,%y%,%w%,%h% 
return

winXP  and ahk unicode


Alpha Bravo
  • Members
  • 1687 posts
  • Last active: Nov 07 2015 03:06 PM
  • Joined: 01 Sep 2011

for better aesthetics, instead of 

gui,add,edit,w300 
Gui, show,x-1000,onmessagereceive

use

Gui, show,Hide,onmessagereceive


DanHunter
  • Members
  • 13 posts
  • Last active: May 17 2013 07:05 AM
  • Joined: 06 Apr 2013

To me, it's aesthetically ugly to have to create the gui at all, instead of just being able to send a message to any EXE or PID, whether it has a window or is windowless. Of course, in the end, it doesn't matter whether it's ugly or beautiful; it just has to work.