Но быстрее всего, конечно, передавать родительский PID в текст скрипта на этапе формирования через переменную.
Выяснилось, что "хакерский" способ передачи текста через WM_SETTEXT работает не совсем надёжно, т. к. это сообщение иногда проскакивает мимо OnMessage() и в таком случае обрабатывается окном, что приводит к смене заголовка на присланный текст. Поэтому посылать строку текста лучше по старинке через WM_COPYDATA, как показано здесь. Если же нужно послать, например, максимум 2 числа в пределах 4Б (на 64-битных интерпретаторах — 8Б) каждое, можно воспользоваться wParam и lParam своего собственного сообщения, зарегистрированного через RegisterWindowMessage(). В каждом из параметров можно послать также и сразу несколько чисел меньшего размера, используя для записи и чтения поразрядный сдвиг.
В примере ниже родительский скрипт посылает строку текста дочернему через WM_COPYDATA. Дочерний скрипт перед завершением посылает родительскому зарегистрированное сообщение WM_INFO, где в wParam единица, в lParam — PID.
ScriptManage := {} ; создаём объект для управления скриптами
ScriptManage.GetScript := Func("GetScript") ; создаём несколько методов
ScriptManage.Run := Func("RunScript")
ScriptManage.Terminate := Func("TerminateScript")
ScriptManage.Send := Func("SendStringToScript")
Gui, +LastFound +AlwaysOnTop
Gui, Add, Edit, x10 y12 vEdit, Эту строчку можно передать дочернему скрипту кнопкой Send.
Gui, Add, Button, x+-79 y+10 w80 gButton, Send
Gui, Add, Button, gButton x10 yp wp Default, Run
GuiControl, Focus, Run
Gui, Show, % "y" A_ScreenHeight//3, % "Мой PID: " ScriptManage.ParentID := DllCall("GetCurrentProcessId")
OnMessage(DllCall("RegisterWindowMessage", Str, "WM_INFO"), "WM_INFO_RECEIVER") ; регистрируем сообщение
OnExit, OnExit ; которое будем использовать для принятия информации от дочернего скрипта
Loop
{
WinSetTitle,,, % "Мой PID: " ScriptManage.ParentID " Время: " A_Hour ":" A_Min ":" A_Sec ":" A_MSec//100
Sleep, 50
}
return
GuiClose:
ExitApp
OnExit:
for k in ScriptManage
if k is integer
ScriptManage.Terminate(k)
ExitApp
Button:
if (A_GuiControl = "Run")
{
ScriptManage.Run(1) ; единица означает, что запускаем первый скрипт
; у нас он один, но может быть сколько угодно
GuiControl,, Edit1, Эту строчку можно передать дочернему скрипту кнопкой Send.
GuiControl,, % A_GuiControl, Terminate
}
else if (A_GuiControl = "Terminate")
ScriptManage.Terminate(1)
else
ScriptManage.Send(1)
return
RunScript(this, n) ; здесь this — вызывающий объект, n — номер скрипта, который будем запускать
{
FilePath := A_Temp "\_MyScript_" A_TickCount ".ahk"
FileAppend, % this.GetScript(n), % FilePath
Run, % FilePath,,, PID
DetectHiddenWindows, On
WinWait, % "ahk_pid" PID
FileDelete, % FilePath
this[n] := {PID: PID} ; сохраняем PID дочернего скрипта в соответствующем ключе вызывающего объекта
}
TerminateScript(this, n)
{
if !this[n].PID
return
WinClose, % "ahk_pid" this[n].PID
this[n].PID := ""
}
SendStringToScript(this, n)
{
DetectHiddenWindows, On
if (this[n].PID = "")
{
MsgBox, 0x2000,, Запустите дочерний скрипт кнопкой Run!
return
}
GuiControlGet, Edit1
VarSetCapacity(COPYDATASTRUCT, A_PtrSize*3)
DataSize := (StrLen(Edit1) + 1)*(A_IsUnicode ? 2 : 1)
NumPut(DataSize, COPYDATASTRUCT, A_PtrSize, "UInt")
NumPut(&Edit1, COPYDATASTRUCT, A_PtrSize*2)
Loop % Fail := 10
SendMessage, WM_COPYDATA := 0x4A,, ©DATASTRUCT,, % "ahk_pid" this[n].PID
until ErrorLevel = 1 && !Fail := ""
if Fail
MsgBox, 0x1010, Ошибка передачи данных, Передача текста не удалась!
}
WM_INFO_RECEIVER(wp, lp)
{
global ScriptManage
Command := wp, PID := lp
if (Command = 1)
{
for k,v in ScriptManage
if (v.PID = PID)
v.PID := ""
GuiControl,, Edit1, Дочерний процесс PID %PID% завершён!
GuiControl,, Terminate, Run
}
}
GetScript(this, n)
{
ParentID := this.ParentID
Script1 =
(
#NoTrayIcon
SetBatchLines, -1
PID := DllCall("GetCurrentProcessId"), ParentID := %ParentID%
OnExit, OnExit
Gui, +AlwaysOnTop +Owner +LastFound
Gui, Color, Gray
Gui, Add, Progress, hwndhControl Border Background606060 x20 y20 w350 h50
Gui, Show, `% "NA w390 h90 Hide", Мой PID: `%PID`%``, мой ParentID: `%ParentID`%
WinGetPos, Xp, Yp, Wp,, `% "ahk_pid" ParentID
WinGetPos, X,, W
WinMove,,, Xp + (Wp - W)//2, Yp + 120
WinShow
Gui, 2:+Parent`%hControl`% -Caption +Lastfound
Gui, 2:Color, 606060
Gui, 2:Font, s20 cFFAA00, Verdana
Gui, 2:Add, Text, x350 y6, Можно отправить сюда текст из главного скрипта!
Gui, 2:Show, `% "NA y0 x" i := 0
WinGetPos,,, Width
OnMessage(0x4A, "WM_COPYDATA_READ")
Loop
{
Gui, 2:Show, `% "NA y0 x" -mod(++i, Width)
Sleep 10
}
return
GuiClose:
ExitApp
OnExit:
PostMessage, DllCall("RegisterWindowMessage", Str, "WM_INFO"), 1, PID,, `% "ahk_pid" ParentID
ExitApp
WM_COPYDATA_READ(wp, lp)
{
global
Text := StrGet(NumGet(lp + A_PtrSize*2))
Gui, 2:New, +Parent`%hControl`% -Caption +Lastfound
Gui, 2:Color, 606060
Gui, 2:Font, s20 cFFAA00, Verdana
Gui, 2:Add, Text, x350 y6, `% Text
Gui, 2:Show, `% "NA y0 x" i := 0
WinGetPos,,, Width
return 1
}
)
return Script%n%
}