1 (изменено: garkin, 2009-05-23 19:30:15)

Тема: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Доброго времени суток, подскажите пожалуйста.
Практическая задача состоит в передаче массива данных указателем оконной процедуре окна, принадлежащего другому скрипту.
Как это можно провернуть?
Как я понимаю, сам по себе обычный указатель('&var') - локальный, относительный адресс, действительный только для текущего процесса.
Каким образом можно представить его в виде глобального адреса, пригодном для применения в соседнем процессе, ну и соответственно считать из него данные в точке назначения?

2

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Вообще-то, сие делается несколько иначе, например, так: INTUIT.ru: Курс: Основы организации ..: Лекция №7: Межпроцессный обмен. Или поищите на тему «file mapping».

3

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Общие модели и принципы: IPC: основы межпроцессного взаимодействия. Обзор технологий.

4 (изменено: garkin, 2009-05-23 21:45:57)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Спасибо.
А сделать на подобии того, что описано в первом топике - никак нельзя?
Как найти нужный участок памяти по указателю и хэндлу процесса?

5

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

А это не то, что тебе нужно?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6 (изменено: garkin, 2009-05-23 22:13:12)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

teadrinker пишет:

А это не то, что тебе нужно?

Спасибо, уже ближе к делу, но есть вопросы:

ProcessName = notepad.exe         ; Имя процесса.
ReadAddress = 0x7C800000          ; Адрес, откуда читать.
ReadSize = 4                      ; Сколько байт читать.
VarSetCapacity(Buf, ReadSize, 0)  ; Буфер, куда считывать.

ReadAdress - это и есть указатель на переменную?

Ну и согласно этому методу придется наряду с указателем передавать pid процесса, так как передача будет происходить через оконную процедуру - этого хотелось бы избежать.
Нет ли способа передать и считать потом адрес физической ячейки памяти, либо привести в пресловутый "глобальный" вид?

7

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Всё одно другой процесс должен откуда-то узнать адрес и длину участка памяти. Так что, лучше поискать реализацию на официальном форуме на тему interprocess site:autohotkey.com - Поиск в Google.

8 (изменено: garkin, 2009-05-23 22:20:54)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

alexii пишет:

Всё одно другой процесс должен откуда-то узнать адрес и длину участка памяти.

В этом проблемы нет, главное натравить его на начало данных, остальное уже отлажено. Если я правильно понял и readaddres==указатель, то достаточно передать сам указатель и pid отправляющего процесса, а дальше - дело техники. Проблему в том, что нужно обойтись одним указателем.

9

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Дело Ваше, но не удивляйтесь потом, ежели какой Касперский его потом грохнет .

10 (изменено: garkin, 2009-05-23 22:34:29)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Блин в uint никак и pid и указатель не запихаешь.

11 (изменено: garkin, 2009-05-23 23:22:13)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Вопрос, а как получить pid текущего скрипта?
Самое простое что пришло в голову - создать временное окно gui и по нему сделать winget, проще нельзя?

12 (изменено: teadrinker, 2009-05-24 02:17:40)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Команда Process.
Кстати, у каждого работающего скрипта УЖЕ есть окно, оно скрыто, и появится, если, нажав правой кнопкой на иконку скрипта в трее, выбрать пункт Open. Так что, PID скрипта можно определить и через его окно:

DetectHiddenWindows On
WinGet, PID, PID, %A_ScriptFullPath%
MsgBox % PID

Но проще так:

MsgBox % DllCall("GetCurrentProcessId")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

garkin
Не уверен, что точно понял Вашу ситуацию, но вот такая идея: у функций SendMessage и PostMessage есть два параметра — lParam и wParam. Вот уже два числа. Можно, например, зарегистрировать в обоих скриптах оконное сообщение с одним и тем же именем, и в нём потом пересылать PID и указатель (ReadAddress). А можно и два сообщения создать, в одном пересылать PID, а в другом — адрес данных и их размер.

Передающий скрипт:

Data =
(
Я теперь скупее стал в желаньях,
Жизнь моя, иль ты приснилась мне?
Словно я весенней гулкой ранью
Проскакал на розовом коне.
)

WinTitle := "Окно №1"  ; Заголовок целевого окна.
PID := DllCall("GetCurrentProcessId")

MsgPID  := DllCall("RegisterWindowMessage", "Str", "MsgPID")
MsgData := DllCall("RegisterWindowMessage", "Str", "MsgData")

F11::  ; Посылать по нажатию F11.
  hWnd := WinExist(WinTitle)
  If not hWnd {
    MsgBox, Не найдено окно:`n%WinTitle%.
    Return
  }

  wParam := PID
  lParam := 0    ; Сюда тоже что-нибудь можно положить.
  PostMessage, MsgPID, wParam, lParam,, ahk_id %hWnd%   ; Посылаем PID.

  wParam := &Data
  lParam := StrLen(Data) + 1  ; Учитываем нулевой байт в конце строки.
  PostMessage, MsgData, wParam, lParam,, ahk_id %hWnd%  ; Адрес данных и размер.
Return

Принимающий скрипт:

WinTitle := "Окно №1"

MsgPID  := DllCall("RegisterWindowMessage", "Str", "MsgPID")
MsgData := DllCall("RegisterWindowMessage", "Str", "MsgData")

OnMessage(MsgPID, "GetPID")   ; Регистрация функций для обработки сообщений.
OnMessage(MsgData, "GetData")

Gui, Show, w400 h300, %WinTitle%
Return


GetPID(wParam, lParam, uMsg, hWnd)
{
  Global PID := wParam
}

GetData(wParam, lParam, uMsg, hWnd)
{
  Global PID
  ReadAddress := wParam             ; Адрес, откуда читать.
  ReadSize := lParam                ; Сколько байт считывать.
  VarSetCapacity(Buf, ReadSize, 0)  ; Буфер, куда считывать.
  
  PROCESS_VM_READ := 0x10           ; Права на процесс.
  
  hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_READ
                                   , Int, False
                                   , UInt, PID)
  If(!hProcess) {
    MsgBox, Не удалось открыть процесс.
    Return
  }
  
  Ret := DllCall("ReadProcessMemory", UInt, hProcess
                                    , UInt, ReadAddress
                                    , UInt, &Buf
                                    , UInt, ReadSize
                                    , UInt, 0)
  
  DllCall("CloseHandle", UInt, hProcess) ; Освобождение хэндла процесса.
  
  If(!Ret) {
    MsgBox, Не удалось прочитать.
    Return
  }
  
  VarSetCapacity(Buf, -1) ; Обновление размера переменной, поскольку запись в неё
                          ; произошла со стороны и AutoHotkey об этом не знает.  
  MsgBox, %Buf%
}

GuiClose:
  ExitApp

14 (изменено: garkin, 2009-05-24 12:23:21)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

YMP, огромное спасибо за пример реализации.
Просто у меня был уже отлаженый код для работы внутри одного скрипта с этим сообщением, где для своих нужд задействованы и lparam  и wparam и была дилетантская надежда, что можно адаптироваться к многопроцессности без смены структуры сообщений, превратив указатель в волшебный "глобальный" вид, вроде far указаетлей dos.

15

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

YMP пишет:

Можно, например, зарегистрировать в обоих скриптах оконное сообщение...

А зачем? В Windows для обмена данными уже существует сообщение WM_COPYDATA.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

teadrinker пишет:

А зачем? В Windows для обмена данными уже существует сообщение WM_COPYDATA.

А ты давно о нём узнал-то? Судя по #5, недавно. Ну а я только что — от тебя.

17

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Каюсь. Но, справедливости ради, о нём можно было узнать ещё несколькими постами ранее, а также в конце этой страницы.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

teadrinker пишет:

Каюсь. Но, справедливости ради, о нём можно было узнать ещё несколькими постами ранее, а также в конце этой страницы.

И что тебе помешало? Давай уж до конца кайся, облегчи душу.

19 (изменено: teadrinker, 2009-05-24 14:23:55)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Всё когда-то случается впервые...:rolleyes: Но лучше поздно, чем никогда!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

20

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Еще вариант  - использовать буфер обмена.

передающий скрипт:
clipboard = 123456

принимающий скрипт:
OnClipboardChange:
MsgBox, %clipboard%
return

21

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Wlad пишет:

Еще вариант  - использовать буфер обмена.

передающий скрипт:
clipboard = 123456

принимающий скрипт:
OnClipboardChange:
MsgBox, %clipboard%
return

Ну уж если совсем извращаться, то можно и невидимый контрол на форме.

22

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

garkin пишет:

Ну уж если совсем извращаться, то можно и невидимый контрол на форме.

Тоже вариант, но все равно придется использовать "PostMessage" для передачи скрипту момента изменения контрола.

23 (изменено: garkin, 2009-05-25 14:45:36)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Не могу заставить работать CopyMemory, подскажите где глюк.

    From:= "abcdefgh"
    To:="1234567890"

    DllCall("CopyMemory"
       , UintP, To
       , UintP, From
       , Uint, 5)

    msgbox % "DllResult: " To    ;И фиг - нет изменений, "1234567890"
ExitApp

24

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Расследование показало, что CopyMemory — это псевдоним RtlCopyMemory, которая в свою очередь — псевдоним memcpy. Ну и типы неправильные были. Так что, видимо, так:

From:= "abcdefgh"
To:="1234567890"

DllCall("msvcrt\memcpy"
       , "Str", To
       , "Str", From
       , "Uint", 5
       , "Cdecl")

msgbox % "DllResult: " To

Ещё можно использовать RtlMoveMemory:

From:= "abcdefgh"
To:="1234567890"

DllCall("RtlMoveMemory"
       , "Str", To
       , "Str", From
       , "Uint", 5)

msgbox % "DllResult: " To

25 (изменено: garkin, 2009-05-25 22:51:23)

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Огромное спасибо. А чем отличается MoveMemory от CopyMemory? Я так понял, что movememory может копировать между перекрывающимися блоками. Она затирает за собой память источника, или просто использует промежуточный буфер?

26

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

garkin пишет:

А чем отличается MoveMemory от CopyMemory? Я так понял, что movememory может копировать между перекрывающимися блоками. Она затирает за собой память источника, или просто использует промежуточный буфер?

Видимо, разница именно в этом. MoveMemory именно копирует, источник она специально не затирает. Если блоки перекрываются и запись должна затирать места, которые ещё не прочитаны, она просто меняет направление копирования на обратное, т.е. копирует с конца к началу. Буфер не используется.

27

Re: AutoHotKey: Передача указателя между двумя процессами (скриптами)

Так началась легенда...