Мой вариант. Предположим, есть 5 скриптов, которые посылают свой текст главному. Посылать они могут в любое время, могут "одновременно". Пусть обработка текстов у главного скрипта занимает какое-то время, а в это время могут приходить новые сообщения. Задача создать из этих сообщений очередь, чтобы они обрабатывались в порядке прибытия, и чтобы никакое сообщение не было потеряно. Если воспользоваться сообщением WM_COPYDATA, то возникает проблема отсутствия его буферизации, т. к. его номер ниже 0x312. Чтобы обойти это, можно воспользоваться своим сообщением, получаемым с помощью RegisterWindowMessage(). Диапазон таких сообщений — 0xC000 - 0xFFFF, т. е. больше 0x312, и такие сообщения будут буферизироваться. В его wp и lp параметрах можно посылать PID отправляющего скрипта, длину и пойнтер переменной с текстом, а затем считывать текст из адресного пространства посылающего скрипта.
Следующий скрипт создаёт пять дочерних скриптов, которые сразу же посылают свои сообщения родительскому скрипту. Обработка каждого занимает две секунды (реализовано с помощью Sleep), сообщения же, которые приходят во время обработки предыдущих, буферизируются, и обрабатываются в свою очередь.
OnMessage(DllCall("RegisterWindowMessage", Str, "WM_INFO"), "WM_INFO_RECEIVER")
ChildrenPIDs := []
Exit := Func("Exit").Bind(ChildrenPIDs)
OnExit(Exit)
Loop 5
ScriptCreator(ChildrenPIDs, A_Index)
Return
Esc:: ExitApp
ScriptCreator(ChildrenPIDs, N)
{
Script =
(
#Persistent
ParentHWND := %A_ScriptHwnd%
MyPID := DllCall("GetCurrentProcessId")
MyNumber := %N%
WM_INFO := DllCall("RegisterWindowMessage", Str, "WM_INFO")
Text := "Это текст от скипта №" MyNumber
wp := (StrLen(Text) * (A_IsUnicode ? 2 : 1)) << 16|MyPID
lp := &Text
DllCall("PostMessage", Ptr, ParentHWND, UInt, WM_INFO, Ptr, wp, Ptr, lp)
)
ChildPID := ExecScript(Script)
ChildrenPIDs.Push(ChildPID)
}
WM_INFO_RECEIVER(wp, lp)
{
static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_READ := 0x10
Critical
PID := wp & 0xFFFF
Pointer := lp
BuffSize := wp >> 16
VarSetCapacity(LocalBuff, BuffSize, 0)
if !hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ, Int, 0, UInt, PID, Ptr)
Return
res := DllCall("ReadProcessMemory", Ptr, hProc, Ptr, Pointer, Ptr, &LocalBuff, Ptr, BuffSize, Ptr, 0)
DllCall("CloseHandle", Ptr, hProc)
if !res
Return
CoordMode, ToolTip
ToolTip % StrGet(&LocalBuff), A_ScreenWidth//2 - 100, A_ScreenHeight//2
Sleep, 1000
ToolTip
Sleep, 1000
}
ExecScript(Script)
{
shell := ComObjCreate("WScript.Shell")
exec := shell.Exec(A_AhkPath " *")
exec.StdIn.Write(script)
exec.StdIn.Close()
return exec.ProcessID
}
Exit(PidArray)
{
DetectHiddenWindows, On
for k, PID in PidArray
WinClose, ahk_pid %PID%
}
Нужно иметь в виду, что скрипт во время демонстрации MsgBox не может мониторить сообщения, поэтому они в примере показываются в ToolTip'е.
Разработка AHK-скриптов:
e-mail
dfiveg@mail.ruTelegram
jollycoder