jugador Posted May 21, 2021 Share Posted May 21, 2021 Instead of using hotkey I want to pass parameter from parent program to close the child program. I try using Run($Exepath & ' True') & StdinWrite($pid, 'True') but it not closing the child program properly. parent expandcollapse popup;~~~~ parent #include <GUIConstantsEx.au3> #include <constants.au3> #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** Global $FName = 'Child.exe' Global $Exepath = @ScriptDir & '\' & $FName Global $pid __gui1() Func __gui1() Local $hGUI = GUICreate("Gui 1", 180, 150, 100, 100) Local $idButton1 = GUICtrlCreateButton("Start", 10, 10, 80, 30) Local $idButton2 = GUICtrlCreateButton("Stop", 10, 50, 80, 30) Local $idLabel = GUICtrlCreateLabel('', 10, 90, 80, 50 ) Local $o_String GUICtrlSetState($idButton2, $GUI_DISABLE) GUISetState(@SW_SHOW, $hGUI) Local $aMsg While 1 $aMsg = GUIGetMsg(1) Switch $aMsg[1] Case $hGUI Switch $aMsg[0] Case $GUI_EVENT_CLOSE ExitLoop Case $idButton1 GUICtrlSetState($idButton1, $GUI_DISABLE) GUICtrlSetState($idButton2, $GUI_ENABLE) GUICtrlSetData($idLabel, 'process start') $o_String = '' $pid = Run($Exepath, '', '', $STDIN_CHILD + $STDOUT_CHILD) GUICtrlSetData($idLabel, $pid) Case $idButton2 GUICtrlSetState($idButton1, $GUI_ENABLE) GUICtrlSetState($idButton2, $GUI_DISABLE) GUICtrlSetData($idLabel, 'process stop') Run($Exepath & ' True') ;StdinWrite($pid, 'True') ;If ProcessExists($pid) Then ;ProcessClose($pid) ;Endif $o_String = StdoutRead($pid) ConsoleWrite( $o_String & @CRLF ) EndSwitch EndSwitch WEnd GUIDelete($hGUI) EndFunc Child ;~~~~ Child ;~ Instead of using hotkey ;~ I want to pass parameter from parent program HotKeySet("{ESC}", "__Flag") Global $bflag = False __Example() ;If ($CmdLine[0] = 0) Then __Example() ;If StringInStr($CmdLine[1], 'True') Then __Flag() ;not closing the program properly Func __Example() Local $i = 0 While 1 If $bflag = True Then __Terminate() ConsoleWrite( $i & @CRLF ) $i = $i + 1 Sleep(250) WEnd EndFunc ;==>__Example Func __Flag() ConsoleWrite( ' ' & $bflag & @CRLF ) $bflag = True ConsoleWrite( ' ' & $bflag & @CRLF ) EndFunc ;==> __Flag() Func __Terminate() ConsoleWrite( ' The End ' & @CRLF ) Exit EndFunc ;==> __Terminate() Link to comment Share on other sites More sharing options...
Subz Posted May 21, 2021 Share Posted May 21, 2021 You could use an external flag for example registry or file, the child keeps watching for this flag and and once changed deletes or modifies the flag back to the default. Hope that makes sense jugador and argumentum 2 Link to comment Share on other sites More sharing options...
argumentum Posted May 21, 2021 Share Posted May 21, 2021 2 hours ago, jugador said: ... I want to pass parameter from parent program to ... ..could also get familiar with IPC technics. ( example: https://www.autoitscript.com/forum/topic/193277-ipc-udf-via-filemapping-20180404/ ) jugador 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
jugador Posted May 22, 2021 Author Share Posted May 22, 2021 @Subz Before posting I try using INI and that’s work. Due to lack of coding knowledge I thought it’s possible to pass parameter to a running application using Run & StdinWrite function. working code using INI as bridge.... parent expandcollapse popup#include <GUIConstantsEx.au3> #include <constants.au3> Global $FName = 'Child.exe' Global $Exepath = @ScriptDir & '\' & $FName Global $__INIPath = @ScriptDir & "\IniFlag.ini" Global $pid __gui1() Func __gui1() Local $hGUI = GUICreate("Gui 1", 180, 150, 100, 100) Local $idButton1 = GUICtrlCreateButton("Start", 10, 10, 80, 30) Local $idButton2 = GUICtrlCreateButton("Stop", 10, 50, 80, 30) Local $idLabel = GUICtrlCreateLabel('', 10, 90, 80, 50 ) Local $o_String GUICtrlSetState($idButton2, $GUI_DISABLE) GUISetState(@SW_SHOW, $hGUI) Local $aMsg While 1 $aMsg = GUIGetMsg(1) Switch $aMsg[1] Case $hGUI Switch $aMsg[0] Case $GUI_EVENT_CLOSE ExitLoop Case $idButton1 GUICtrlSetState($idButton1, $GUI_DISABLE) GUICtrlSetState($idButton2, $GUI_ENABLE) GUICtrlSetData($idLabel, 'process start') IniWrite($__INIPath, "Flag_Param", "Child_flag", "False") $o_String = '' $pid = Run($Exepath, '', '', $STDIN_CHILD + $STDOUT_CHILD) Case $idButton2 GUICtrlSetState($idButton1, $GUI_ENABLE) GUICtrlSetState($idButton2, $GUI_DISABLE) GUICtrlSetData($idLabel, 'process stop') IniWrite($__INIPath, "Flag_Param", "Child_flag", "True") ProcessWait($FName) $o_String = StdoutRead($pid) ConsoleWrite( $o_String & @CRLF ) EndSwitch EndSwitch WEnd GUIDelete($hGUI) EndFunc Child ;~~~~ Child Global $bflag = False __Example() Func __Example() Local $__INIPath = @ScriptDir & "\IniFlag.ini" Local $o_String Local $i = 0 While 1 $o_String = IniRead($__INIPath, "Flag_Param", "Child_flag", "False") If StringInStr($o_String, "True") Then __Flag() If $bflag = True Then __Terminate() ConsoleWrite( $i & @CRLF ) $i = $i + 1 Sleep(250) WEnd EndFunc ;==>__Example Func __Flag() ConsoleWrite( ' ' & $bflag & @CRLF ) $bflag = True ConsoleWrite( ' ' & $bflag & @CRLF ) EndFunc ;==> __Flag() Func __Terminate() ConsoleWrite( ' The End ' & @CRLF ) Exit EndFunc ;==> __Terminate() @argumentum I haven’t look into your udf but I will try to make it work using your udf or _WM_COPYDATA. argumentum 1 Link to comment Share on other sites More sharing options...
jugador Posted May 23, 2021 Author Share Posted May 23, 2021 (edited) WM_COPYDATA taken from @KaFu Enforce Single Instance of Program via WM_COPYDATA thread. parent expandcollapse popup#include <GUIConstantsEx.au3> #include <constants.au3> Global $TITLE_RECEIVER = 'Test_Child_Window' global const $WM_COPYDATA = 0x004A Global $FName = 'Child.exe' Global $Exepath = @ScriptDir & '\' & $FName Global $pid __gui1() Func __gui1() Local $h_Pidhwnd Local $hGUI = GUICreate("Gui 1", 180, 150, 100, 100) Local $idButton1 = GUICtrlCreateButton("Start", 10, 10, 80, 30) Local $idButton2 = GUICtrlCreateButton("Stop", 10, 50, 80, 30) Local $idLabel = GUICtrlCreateLabel('', 10, 90, 80, 50 ) Local $o_String GUICtrlSetState($idButton2, $GUI_DISABLE) GUISetState(@SW_SHOW, $hGUI) Local $aMsg While 1 $aMsg = GUIGetMsg(1) Switch $aMsg[1] Case $hGUI Switch $aMsg[0] Case $GUI_EVENT_CLOSE ExitLoop Case $idButton1 GUICtrlSetState($idButton1, $GUI_DISABLE) GUICtrlSetState($idButton2, $GUI_ENABLE) GUICtrlSetData($idLabel, 'process start') $o_String = '' $pid = Run($Exepath, '', '', $STDIN_CHILD + $STDOUT_CHILD) Case $idButton2 GUICtrlSetState($idButton1, $GUI_ENABLE) GUICtrlSetState($idButton2, $GUI_DISABLE) GUICtrlSetData($idLabel, 'process stop') __WM_COPYDATA_SendData(WinGetHandle($TITLE_RECEIVER), 'True') sleep(500) $o_String = StdoutRead($pid) ConsoleWrite( $o_String & @CRLF ) EndSwitch EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>gui1 ;https://www.autoitscript.com/forum/topic/106895-enforce-single-instance-of-program-via-wm_copydata/?do=findComment&comment=754297 Func __WM_COPYDATA_SendData($hWnd, $sData) If Not IsHWnd($hWnd) Then Return 0 if $sData = "" then $sData = " " Local $tCOPYDATA, $tMsg $tMsg = DllStructCreate("char[" & StringLen($sData) + 1 & "]") DllStructSetData($tMsg, 1, $sData) $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr") DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1) DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg)) $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA)) If (@error) Or ($Ret[0] = -1) Then Return 0 Return 1 EndFunc ;==>_SendData Child expandcollapse popup;~~~~ Child #include <WindowsConstants.au3> Global $ChildGui Global $TITLE_RECEIVER = 'Test_Child_Window' Global $sMsg_Rcvd Global $bflag = False __Example() Func __Example() $ChildGui = GUICreate($TITLE_RECEIVER, 200, 200) GUIRegisterMsg($WM_COPYDATA, '_WM_COPYDATA') GUISetState(@SW_HIDE) Local $i = 0 While 1 If StringInStr($sMsg_Rcvd, "True") Then __Flag() If $bflag = True Then __Terminate() ConsoleWrite( $i & @CRLF ) $i = $i + 1 Sleep(250) WEnd EndFunc ;==>__Example Func __Flag() ConsoleWrite( ' ' & $bflag & @CRLF ) $bflag = True ConsoleWrite( ' ' & $bflag & @CRLF ) EndFunc ;==> __Flag() Func __Terminate() ConsoleWrite( ' The End ' & @CRLF ) GUIDelete($ChildGui) ;<<<<<<<<<< Exit EndFunc ;==> __Terminate() Func _WM_COPYDATA($hWnd, $msgID, $wParam, $lParam) Local $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr", $lParam) Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3)) $sMsg_Rcvd = DllStructGetData($tMsg, 1) Return 0 EndFunc ;==>_WM_COPYDATA @KaFu & @argumentum if have time do check if any error in code. Is there any technique to receive message without using hidden gui in child ..... Thanks. Edited May 23, 2021 by jugador Link to comment Share on other sites More sharing options...
JockoDundee Posted May 23, 2021 Share Posted May 23, 2021 57 minutes ago, jugador said: Is there any technique to receive message without using hidden gui in child yes, use a gui that’s not hidden jugador 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
jugador Posted May 23, 2021 Author Share Posted May 23, 2021 (edited) @JockoDundee Sorry for my English but I am saying can it be done without using gui in child. GUIRegisterMsg will not work without gui so i guess it's needed. Edited May 23, 2021 by jugador Link to comment Share on other sites More sharing options...
jugador Posted May 24, 2021 Author Share Posted May 24, 2021 Using @trancexx mailslot parent expandcollapse popup#include <GUIConstantsEx.au3> #include <constants.au3> #include "MailSlot.au3" Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest" Global $FName = 'Child.exe' Global $Exepath = @ScriptDir & '\' & $FName Global $pid __gui1() Func __gui1() Local $hGUI = GUICreate("Gui 1", 180, 150, 100, 100) Local $idButton1 = GUICtrlCreateButton("Start", 10, 10, 80, 30) Local $idButton2 = GUICtrlCreateButton("Stop", 10, 50, 80, 30) Local $idLabel = GUICtrlCreateLabel('', 10, 90, 80, 50 ) Local $o_String GUICtrlSetState($idButton2, $GUI_DISABLE) GUISetState(@SW_SHOW, $hGUI) Local $aMsg While 1 $aMsg = GUIGetMsg(1) Switch $aMsg[1] Case $hGUI Switch $aMsg[0] Case $GUI_EVENT_CLOSE ExitLoop Case $idButton1 GUICtrlSetState($idButton1, $GUI_DISABLE) GUICtrlSetState($idButton2, $GUI_ENABLE) GUICtrlSetData($idLabel, 'process start') $o_String = '' $pid = Run($Exepath, '', '', $STDIN_CHILD + $STDOUT_CHILD) Case $idButton2 GUICtrlSetState($idButton1, $GUI_ENABLE) GUICtrlSetState($idButton2, $GUI_DISABLE) GUICtrlSetData($idLabel, 'process stop') _MailSlotWrite($sMailSlotName, 'True') If @error Then ExitLoop sleep(500) $o_String = StdoutRead($pid) ConsoleWrite( $o_String & @CRLF ) EndSwitch EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>gui1 Child expandcollapse popup;~~~~ Child1 #include "MailSlot.au3" Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest" Global $hMailSlot = _MailSlotCreate($sMailSlotName) If @error Then MsgBox(48 + 262144, "MailSlot", "Failed to create new account!" & @CRLF & "Probably one using that 'address' already exists.") Exit EndIf Global $bflag = False __Example() Func __Example() Local $iCount Local $iSize Local $sData Local $i = 0 While 1 $iCount = _MailSlotGetMessageCount($hMailSlot) If $iCount > 0 Then $iSize = _MailSlotCheckForNextMessage($hMailSlot) ConsoleWrite( "$iSize: " & $iSize & @CRLF ) $sData = _MailSlotRead($hMailSlot, $iSize, 1) ConsoleWrite( "$sData: " & $sData & @CRLF ) Endif If StringInStr($sData, "True") Then __Flag() If $bflag = True Then __Terminate() ConsoleWrite( $i & @CRLF ) $i = $i + 1 Sleep(250) WEnd EndFunc ;==>__Example Func __Flag() ConsoleWrite( ' ' & $bflag & @CRLF ) $bflag = True ConsoleWrite( ' ' & $bflag & @CRLF ) EndFunc ;==> __Flag() Func __Terminate() ConsoleWrite( ' The End ' & @CRLF ) _CloseMailAccount($hMailSlot) Exit EndFunc ;==> __Terminate() Func _CloseMailAccount(ByRef $hHandle) If _MailSlotClose($hHandle) Then $hHandle = 0 ConsoleWrite( "Account succesfully closed." & @CRLF ) Else ConsoleWrite( "Account could not be closed!" & @CRLF ) EndIf EndFunc ;==>_CloseMailAccount Link to comment Share on other sites More sharing options...
JockoDundee Posted May 24, 2021 Share Posted May 24, 2021 2 hours ago, jugador said: Using @trancexx mailslot Kudos for actually doing the work and trying different approaches on your own. Rare. As for your initial attempt, I think you were pretty close; the main prob i saw was that the Child was not reading from the Console and the Parent was not reading all the time from the child, and that you had commented out the StdOutWrite. See if this works for you, my changes are noted in the margin: Parent expandcollapse popup;~~~~ parent #include <GUIConstantsEx.au3> #include <constants.au3> #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** Global $FName = 'Child.exe' Global $Exepath = @ScriptDir & '\' & $FName Global $pid __gui1() Func __gui1() Local $hGUI = GUICreate("Gui 1", 180, 150, 100, 100) Local $idButton1 = GUICtrlCreateButton("Start", 10, 10, 80, 30) Local $idButton2 = GUICtrlCreateButton("Stop", 10, 50, 80, 30) Local $idLabel = GUICtrlCreateLabel('', 10, 90, 80, 50 ) Local $o_String GUICtrlSetState($idButton2, $GUI_DISABLE) GUISetState(@SW_SHOW, $hGUI) Local $aMsg While 1 $aMsg = GUIGetMsg(1) Switch $aMsg[1] Case $hGUI Switch $aMsg[0] Case $GUI_EVENT_CLOSE ExitLoop Case $idButton1 GUICtrlSetState($idButton1, $GUI_DISABLE) GUICtrlSetState($idButton2, $GUI_ENABLE) GUICtrlSetData($idLabel, 'process start') $o_String = '' $pid = Run($Exepath, '', '', $STDIN_CHILD + $STDOUT_CHILD) GUICtrlSetData($idLabel, $pid) Case $idButton2 GUICtrlSetState($idButton1, $GUI_ENABLE) GUICtrlSetState($idButton2, $GUI_DISABLE) GUICtrlSetData($idLabel, 'process stop') ;Run($Exepath & ' True') ;Jocko Delete StdinWrite($pid, 'True') ;Jocko Add ;If ProcessExists($pid) Then ;ProcessClose($pid) ;Endif ;$o_String = StdoutRead($pid) ;Jocko Delete ;ConsoleWrite( $o_String & @CRLF ) ;Jocko Delete EndSwitch EndSwitch $o_String = StdoutRead($pid) ;Jocko Add If $o_String Then ConsoleWrite( $o_String & @CRLF ) ;Jocko Add WEnd GUIDelete($hGUI) EndFunc Child ;~~~~ Child ;~ Instead of using hotkey ;~ I want to pass parameter from parent program HotKeySet("{ESC}", "__Flag") Global $bflag = False __Example() ;If ($CmdLine[0] = 0) Then __Example() ;If StringInStr($CmdLine[1], 'True') Then __Flag() ;not closing the program properly Func __Example() Local $i = 0 While 1 If $bflag = True Then __Terminate() ConsoleWrite( $i & @CRLF ) $i = $i + 1 Sleep(250) If ConsoleRead()='True' Then __Flag() ;Jocko Add WEnd EndFunc ;==>__Example Func __Flag() ConsoleWrite( ' ' & $bflag & @CRLF ) $bflag = True ConsoleWrite( ' ' & $bflag & @CRLF ) EndFunc ;==> __Flag() Func __Terminate() ConsoleWrite( ' The End ' & @CRLF ) Exit EndFunc ;==> __Terminate() jugador 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
jugador Posted May 24, 2021 Author Share Posted May 24, 2021 Quote StdoutRead() reads from the console standard output stream of a child process ConsoleRead() is normally used by console applications to read input from a parent process. @JockoDundee now I see my mistake after reading ConsoleRead in help file. I was using StdoutRead to read input from a parent process. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now