1 (изменено: Drugoy, 2014-03-17 02:47:43)

Тема: AHK: eval() hotstrings

Хочется скрипт, который бы умел читать содержимое внешнего файла и использовать записанные в этом файле слова и сопоставленные им фразы, как условия и результаты для hotstring'ов.
Т.е. если файл содержит

WOT|Web of Trust
MzFx|Mozilla Firefox
B.Y.O.B|bring your own booze

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

::WOT::
msgbox Web of Trust
Return
::MzFx::
msgbox Mozilla Firefox
Return
::B.Y.O.B::
msgbox bring your own booze
Return

2 (изменено: Irbis, 2014-03-17 11:17:16)

Re: AHK: eval() hotstrings

Hotstring.ahk  (Топик)

#Include Hotstring.ahk

Array := {}
Loop, Read, %A_ScriptDir%\Hotstrings.ini {
   tmp := StrSplit(A_LoopReadLine,"|")
   Array.Insert(tmp[1],tmp[2])
   Hotstring(tmp[1],"MsgBox")
}
return

MsgBox:
MsgBox % Array[$]
Return

Hotstrings.ini

WOT|Web of Trust
MzFx|Mozilla Firefox
B.Y.O.B|bring your own booze

3

Re: AHK: eval() hotstrings

Irbis,
вау, спасибо, работает всё как надо!

4

Re: AHK: eval() hotstrings

Пожалуйста

5

Re: AHK: eval() hotstrings

Irbis
только 1 вопрос возник: у обычных хотстрингов можно выставлять настройки, как выставить их в этом скрипте?
Конкретно надо только это:

#Hotstring EndChars `n
#Hotstring c0

6

Re: AHK: eval() hotstrings

В Hotstring() переменная breakChars содержит EndChars, а переменная Shift отвечает за чувствительность к регистру символов.
Алгоритм элементарный, на все клавиши вешается один обработчик, в статической typed хранится текущая фраза, дополняемая из A_thisHotkey.

7

Re: AHK: eval() hotstrings

В целом метод с хоткеями на все значимые клавиши трудно назвать оптимальным - гораздо лучше воспользоваться предложенным teadrinker'ом способом установки хука на события. Но способ с hotstring.ahk требует минимальных исправлений кода, тут уж кому как удобней - "шашечки или ехать", как говорится.

По поводу

#Hotstring EndChars `n
#Hotstring c0

В Hotstring() третий передаваемый параметр отвечает за то, как будет интерпретирована входная строка. В данном случае нам подходит "3", строка как выражение для RegEx.

Пример Hotstrings.ini

i)WOT\n|Web of Trust
i)MzFx|Mozilla Firefox
B.Y.O.B|bring your own booze

В первой строке нечуствительный к регистру хотстринг ( i) ), срабатывает только по клавише "ввод" ( \n )
Во второй строке то же самое, но без \n - хотстринг сработает сразу.
Третья строка - как и раньше, строгое соответствие, без нажатия клавиши "ввод".

Сам исправленый скрипт:

#Include hotstring.ahk

Array := {}
Loop, Read, %A_ScriptDir%\Hotstrings.ini
{
   tmp := StrSplit(A_LoopReadLine,"|")
   Array.Insert(RegExReplace(tmp[1], "[\i\),\\n]"), tmp[2])
   Hotstring(tmp[1],"MsgBox",3)
}
return

MsgBox:
MsgBox % Array[RegExReplace($, "\n")]
Return

8

Re: AHK: eval() hotstrings

bWRmeA, нет, breakChars это не EndChars, а список кнопок, нажатие которых отключает срабатывание hotstring'ов, в случае если они были дописаны после нажатия одного из breakChar'ов.
Сейчас EndChars вообще нет: hotstring'и срабатывают сразу как в них был напечатан последний символ.
А вот по поводу переменной Shift вы оказались правы, закомментировал тот кусок кода и хотстринги стали работать как с флагом c0.
По-поводу алгоритма работы библиотеки - мне всё равно не понятно как она это делает. Я не вижу ни где hotstring'и задаются + я плохо пока разбираюсь с массивами и не понимаю, например, что такое

% Array[$]

9

Re: AHK: eval() hotstrings

Irbis
спасибо за заметку про mode=3 (regex) и использование \n в конце trigger word'ов у прописанных hotstring'ов - это как раз то, что нужно.
По поводу хуков - чтиво интересное, вот только по логике в статье пропущен следующий шаг, самый интересный и самый важный: ну повесили мы хуки на клавиатуру и или мышь, где и как это можно применять?
Хорошо ещё что приведены несколько примеров применения хуков, в том числе AHK: Определение символов, посылаемых с клавиатуры, что вроде бы как раз то, что понадобилось бы мне здесь.
Но этот скрипт позволяет лишь узнать историю нажатия клавиш, из чего, допустим, можно определить, что было напечатано (хотя, это не совсем так), а дальше что? писать проверяльщика, который после каждого напечатанного символа будет учитывая историю ранее напечатанных символов вручную проверять не была ли напечатана одна из trigger-фраз из нашего внешнего файла? Это как-то совсем оверкилл, к тому же и работать оно будет всё равно с ошибками: пользователь открыл файл, напечатал mz, открыл браузер и в адресную строку напечатал fx - скрипт подумал, что было напечатано mzfx и сработал, fail.
Спасибо, пока ограничусь hotstrings().

10 (изменено: Irbis, 2014-03-20 01:52:35)

Re: AHK: eval() hotstrings

$ - в данном случай просто имя переменной, можно его глобально заменить на MyVar, для примера.
В ней в момент вызова содержится ключ для пары ключ:значение ассоциативного массива, и тогда

MsgBox % Array[$]

выведет собственно значение для этого ключа.

Upd: По поводу переменной Shift, если ее закомментировать, то в таком случае потеряется часть функционала, хотя для этого как раз и есть i) ,чтобы гибко управлять чувствительностью к регистру строки. Врочем, решать ТС'у

11

Re: AHK: eval() hotstrings

Drugoy пишет:

...
Но этот скрипт позволяет лишь узнать историю нажатия клавиш, из чего, допустим, можно определить, что было напечатано (хотя, это не совсем так), а дальше что?...

А дальше "писать проверяльщика".
Уверен, что по именно такому алгоритму действуют программы с функцией автозамены, как punto и прочие.
Ставится хук на события клавиатуры и мыши, тестируемая строка "прирастает" при наборе пользователем и сравнивается с заданными шаблонами, а при нажатии нетекстовых клавиш или сочетаний (Alt+клавиша, Ctrl+клавиша и т.д.) или кнопок мыши - строка обнуляется.

12

Re: AHK: eval() hotstrings

Drugoy пишет:

Irbis к тому же и работать оно будет всё равно с ошибками: пользователь открыл файл, напечатал mz, открыл браузер и в адресную строку напечатал fx - скрипт подумал, что было напечатано mzfx и сработал, fail.

Если проверку на смену окна/контрола/движение мыши и нетекстовых клавиш поставить, то все будет работать как надо.

13 (изменено: Drugoy, 2014-03-20 16:44:06)

Re: AHK: eval() hotstrings

Irbis,
а можно ли как-то в скрипте в коде записать в переменную trigger phrase к определённому (заранее известному) trigger keyword'у?
т.е. из примера выше я, допустим, хочу чтобы у меня переменная browser содержала значение, соответствующее trigger keyword'у "MzFx" trigger phrase, т.е. "Mozilla Firefox".

EDIT:
Разобрался, надо просто после tmp := StrSplit(A_LoopReadLine, "|") добавить проверку совпадает ли tmp[1] с MzFx и если да, то записать содержимое tmp[2] в нужную переменную.

14

Re: AHK: eval() hotstrings

Я не знаю стоит ли создавать для этого новую тему или писать сюда, но т.к. всё-таки проблема связана и с этой темой - то решил написать сюда.

Мой скрипт мутировал в такое:

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, Force
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
; #Include Hotstring.ahk

Global extractTo := A_Temp "\executor"  ; Path where to extract archives' contents to.

Array := {}
Loop, Read, %A_ScriptDir%\Hotstrings.ini    ; This files contents consist of lines that each consists of two parts separated with a pipe. Left part is the hotstring trigger text and the right part is the full path.
{
    tmp := StrSplit(A_LoopReadLine, "|")
    If (tmp[1] == "archiver")   ; If the left part of a line is "archiver".
        Global archiver := tmp[2]   ; Then store the path from the right part of that line into a variable 'archiver' that will later be used for reaching files inside of archives.
    Array.Insert(RegExReplace(tmp[1], "[\i\),`]"), tmp[2])
    Hotstring(tmp[1], "subRoutine", 3)
}
Return

#IfWinActive, ahk_exe explorer.exe ahk_class #32770

subRoutine:
    mainFunc(Array[$])
Return

mainFunc(input)
{
    ControlGetFocus, activeControl, A
    If (activeControl == "Edit1")   ; Win+R window: "Execute" (or "Выполнить" in Ru OS locale).
    {
        WinClose    ; Close the "Execute" (or "Выполнить" in Ru OS locale) window.
        IfInString, input, !    ; Paths with "!" are the ones pointing to the files inside archives.
; Example path to an executable inside an archive: C:\Test.rar!subfolder\runme.exe
        {
            partialPath := StrSplit(input, "!") ; partialPath[1] contains the path to the archive. partialPath[2] contains the relative path to the executable withing the archive (where root is the archive itself).
            archiveName := SubStr(partialPath[1], InStr(partialPath[1], "\",, 0), InStr(partialPath[1], ".",, 0) - InStr(partialPath[1], "\",, 0))  ; Archive's name (without extension) will be used to name the temporary folder where it will get unpacked to.
            RunWait, % """" archiver """ x """ partialPath[1] """ -aoa -y -o""" extractTo archiveName """",, Hide   ; Use the archiver to unpack the files.
            RunWait, % extractTo archiveName "\" partialPath[2] ; Run the needed executable from the unpacked files.
            FileRemoveDir, % extractTo archiveName, 1   ; Remove the unpacked stuff after it got closed.
        }
        Else    ; The path points to a file outside archive.
            Run, % Array[RegExReplace($, "`")]
    }
}

Он позволяет запускать программы, в том числе программы внутри архивов по заранее заданным alias'ам для этих программ.
Alias'ы хранятся во внешнем файле %A_ScriptDir%\Hotstrings.ini
Содержимое этого файла должно выглядеть вот так:

archiver|C:\Program files\7-zip\7z.exe
7z`|C:\Program files\7-zip\7zFM.exe
7zip`|C:\Program files\7-zip\7zFM.exe
7-zip`|C:\Program files\7-zip\7zFM.exe
rar`|C:\Program files\WinRar\winrar.exe
unrar`|C:\Program files\WinRar\winrar.exe
winrar`|C:\Program files\WinRar\winrar.exe
ape`|C:\Soft\Utils\AppPathsEditor.zip!ape.exe
apppaths`|C:\Soft\Utils\AppPathsEditor.zip!ape.exe
junction`|C:\Soft\Utils\Junction.zip!Junction.exe
junctions`|C:\Soft\Utils\Junction.zip!Junction.exe
junc`|C:\Soft\Utils\Junction.zip!Junction.exe
junk`|C:\Soft\Utils\Junction.zip!Junction.exe
switcherx`|C:\Soft\Utils\Switcherx.rar!SwitcherX\SwitcherX.exe

Пользоваться скриптом так: запустить его, нажать Win+R (откроется окно "выполнить"), туда вбить "ape`" (без кавычек, но со штрихом) и откроется ape.exe из архива C:\Soft\Utils\AppPathsEditor.zip

Штука в том, что если была попытка запустить файл из архива - то архив сначала распаковывается (используя архиватор, путь к которому задаётся внутри hotstrings.ini в alias'е "archiver"), затем RunWait'ом открывается нужный исполняемый файл. RunWait нужен для того, чтобы по закрытии программы были удалены все распакованные из архива файлы. Т.е. реализована чистка за собой.
Но проблема в том, что не получается одновременно запустить 2 программы, если они обе заархивированы.
Не получается как раз из-за RunWait'а.

Как решить проблему через SetTimer?
Пробовал вот так

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, Force
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
; #Include Hotstring.ahk

Global extractTo := A_Temp "\executor"    ; Path where to extract archives' contents to.

Array := {}
Loop, Read, %A_ScriptDir%\Hotstrings.ini    ; This files contents consist of lines that each consists of two parts separated with a pipe. Left part is the hotstring trigger text and the right part is the full path.
{
    tmp := StrSplit(A_LoopReadLine, "|")
    If (tmp[1] == "archiver")    ; If the left part of a line is "archiver".
        Global archiver := tmp[2]    ; Then store the path from the right part of that line into a variable 'archiver' that will later be used for reaching files inside of archives.
    Array.Insert(RegExReplace(tmp[1], "[\i\),`]"), tmp[2])
    Hotstring(tmp[1], "subRoutine", 3)
}
Return

#IfWinActive, ahk_exe explorer.exe ahk_class #32770

subRoutine:
    mainFunc(Array[$])
Return

timer:
        waitAndRemove(runThis, removeThis)
Return


mainFunc(input)
{
    ControlGetFocus, activeControl, A
    If (activeControl == "Edit1")    ; Win+R window: "Execute" (or "Выполнить" in Ru OS locale).
    {
        WinClose    ; Close the "Execute" (or "Выполнить" in Ru OS locale) window.
        IfInString, input, !    ; Paths with "!" are the ones pointing to the files inside archives.
; Example path to an executable inside an archive: C:\Test.rar!subfolder\runme.exe
        {
            partialPath := StrSplit(input, "!")    ; partialPath[1] contains the path to the archive. partialPath[2] contains the relative path to the executable withing the archive (where root is the archive itself).
            archiveName := SubStr(partialPath[1], InStr(partialPath[1], "\",, 0), InStr(partialPath[1], ".",, 0) - InStr(partialPath[1], "\",, 0))    ; Archive's name (without extension) will be used to name the temporary folder where it will get unpacked to.
            RunWait, % """" archiver """ x """ partialPath[1] """ -aoa -y -o""" extractTo archiveName """",, Hide    ; Use the archiver to unpack the files.
            Global runThis := extractTo archiveName "\" partialPath[2]
            Global removeThis := extractTo archiveName
            SetTimer, timer, -1
            ; RunWait, % extractTo archiveName "\" partialPath[2]    ; Run the needed executable from the unpacked files.
            ; FileRemoveDir, % extractTo archiveName, 1    ; Remove the unpacked stuff after it got closed.
        }
        Else    ; The path points to a file outside archive.
            Run, %input%
    }
    ListLines
}

waitAndRemove(runWait, fileRemoveDir)
{
msgbox runWait: '%runWait%'`nfileRemoveDir: '%fileRemoveDir%'`n
    RunWait, %runWait%
    FileRemoveDir, %fileRemoveDir%, 1    ; Remove the unpacked stuff after it got closed.
}

Но так почему-то не создаются новые псевдо-thread'ы и скрипт перестаёт реагировать на хотстринги когда висит на RunWait'е.

Второй вариант решения проблемы мне видится в том, чтобы создать массив PID'ов и сопоставленных им имён папок (куда были распакованы архивы), которые проверять settimer'ом на жизненность и удалять соответствующую папку, если PID умер.
Вариант с массивами пока не рассматривается как решение (хочется всё-таки получше с thread'ами разобраться).

15 (изменено: bWRmeA, 2014-04-10 14:16:46)

Re: AHK: eval() hotstrings

Но так почему-то не создаются новые псевдо-thread'ы

Settimer не создаёт новые псевдо-треды при вызове, а ставит в очередь вызов метки. Если Settimer для текущей метки уже был вызван - вызов смещается в очереди (или нет, в зависимоти от параметров вызова).

Чтобы создать два асинхронных потока нужно иметь две метки и выполнить settimer два раза. Тот поток, который создан ранее начнёт выполнение как только основной поток использует sleep или выполнит все операции, второй асинхронный поток начнёт выполнение как только первый вызовет sleep (при условии что приоритеты потоков при вызове settimer указаны одинаковые)

Под sleep подразумевается режим ожидания интерпретатора.

Ну и пример для самых маленьких:

#Persistent

SetTimer 1, -1
SetTimer 1, -300
return

1:
    MsgBox
    return

Esc::ExitApp
#Persistent

SetTimer 1, -1
SetTimer 2, -300
return

2:
1:
    MsgBox
    return

Esc::ExitApp

В первом случае 1 msgbox через 300 мс, во втором - 2


            Global runThis := extractTo archiveName "\" partialPath[2]
            Global removeThis := extractTo archiveName
            SetTimer, timer, -1

Это имеет смысл если ты уверен, что следующий вызов mainfunc произойдёт гарантированно после того как waitAndRemove возьмёт из этих переменных  значения указанные в предыдущем вызове mainfunc.  Если такой уверенности нет, то нужно организовать очередь вызовов - mainfunc пишет в очередь нужные параметры и для каждой записи вызывает асинхронный waitAndRemove, waitAndRemove читает и удаляет из очереди взятые на исполнение параметры (когда угодно читает, и удаляет, но гаратированно не теряет параметры в случае если между вызоывами mainfunc не удалось выполнить асинронный waitAndRemove)

16

Re: AHK: eval() hotstrings

спасибо, проблему решил

+ открыть спойлер
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, Force
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
; #Include Hotstring.ahk
#MaxThreadsPerHotkey, 20

Global extractTo := A_Temp "\executor"    ; Path where to extract archives' contents to.

Array := {}
Loop, Read, %A_ScriptDir%\Hotstrings.ini    ; This files contents consist of lines that each consists of two parts separated with a pipe. Left part is the hotstring trigger text and the right part is the full path.
{
    tmp := StrSplit(A_LoopReadLine, "|")
    If (tmp[1] == "archiver")    ; If the left part of a line is "archiver".
        Global archiver := tmp[2]    ; Then store the path from the right part of that line into a variable 'archiver' that will later be used for reaching files inside of archives.
    Array.Insert(RegExReplace(tmp[1], "[\i\),`]"), tmp[2])
    Hotstring(tmp[1], "subRoutine", 3)
}
Return

#IfWinActive, ahk_exe explorer.exe ahk_class #32770

subRoutine:
    mainFunc(Array[$])
Return

mainFunc(input)
{
    ControlGetFocus, activeControl, A
    If (activeControl == "Edit1")    ; Win+R window: "Execute" (or "Выполнить" in Ru OS locale).
    {
        WinClose    ; Close the "Execute" (or "Выполнить" in Ru OS locale) window.
        IfInString, input, !    ; Paths with "!" are the ones pointing to the files inside archives.
; Example path to an executable inside an archive: C:\Test.rar!subfolder\runme.exe
        {
            partialPath := StrSplit(input, "!")    ; partialPath[1] contains the path to the archive. partialPath[2] contains the relative path to the executable withing the archive (where root is the archive itself).
            archiveName := SubStr(partialPath[1], InStr(partialPath[1], "\",, 0), InStr(partialPath[1], ".",, 0) - InStr(partialPath[1], "\",, 0))    ; Archive's name (without extension) will be used to name the temporary folder where it will get unpacked to.
            RunWait, % """" archiver """ x """ partialPath[1] """ -aoa -y -o""" extractTo archiveName """",, Hide    ; Use the archiver to unpack the files.
            Global runThis := extractTo archiveName "\" partialPath[2]
            Global removeThis := extractTo archiveName
            waitAndRemove(runThis, removeThis)
        }
        Else    ; The path points to a file outside archive.
            Run, %input%
    }
    ListLines
}

waitAndRemove(runWait, fileRemoveDir)
{
    RunWait, %runWait%
    FileRemoveDir, %fileRemoveDir%, 1    ; Remove the unpacked stuff after it got closed.
}

17

Re: AHK: eval() hotstrings

Irbis пишет:
#Include hotstring.ahk

Array := {}
Loop, Read, %A_ScriptDir%\Hotstrings.ini
{
   tmp := StrSplit(A_LoopReadLine,"|")
   Array.Insert(RegExReplace(tmp[1], "[\i\),\\n]"), tmp[2])
   Hotstring(tmp[1],"MsgBox",3)
}
return

MsgBox:
MsgBox % Array[RegExReplace($, "\n")]
Return

В случае если в hotstrings.ini идёт любая из этих записей

anvir`|C:\Soft\Portable soft\AnvirTaskManager\AnVir.exe
vir`|C:\Soft\Portable soft\AnvirTaskManager\AnVir.exe

она портится этой строкой

Array.Insert(RegExReplace(tmp[1], "[\i\),\\n]"), tmp[2])

так, что из левой части выпадает i:
hotstring'и добавляются верные, но в массив они попадают как anvr` и vr`.
Причём хотстринг срабатывает именно при наборе anvir` и vir`, но т.к. в массиве этих значений нет, то скрипт не может и вызвать программу по пути указанному в правой части строки в hotstrings.ini
Проверить это можно добавив строку

msgbox % "RegExReplace(tmp[1], ""[\i\),\\n]""): '" RegExReplace(tmp[1], "[\i\),`]") "'"

после или перед Array.Insert.

Конечно же, был неправильно составлен RegEx needle. Должно быть что-то типа "^i\)|\\n$". Внутри квадратных скобок перечисляются отдельные символы, они не составляют последовательностей.

18

Re: AHK: eval() hotstrings

а как выставить endchar'ом Enter но так, чтобы он не отсылался в окно, куда набирается хотстринг?

19 (изменено: Drugoy, 2014-05-29 14:30:22)

Re: AHK: eval() hotstrings

nvm

20

Re: AHK: eval() hotstrings

Drugoy пишет:

Хочется скрипт, который бы умел читать содержимое внешнего файла и использовать записанные в этом файле слова и сопоставленные им фразы, как условия и результаты для hotstring'ов.
Т.е. если файл содержит

WOT|Web of Trust
MzFx|Mozilla Firefox
B.Y.O.B|bring your own booze

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

::WOT::
msgbox Web of Trust
Return
::MzFx::
msgbox Mozilla Firefox
Return
::B.Y.O.B::
msgbox bring your own booze
Return

У меня похожая задача (поэтому не стал создавать отдельную тему).
Мне хочется строки использовать как исходный код.
eval позволяет указать интерпретатору, что строковая переменная является выражением.
А мне хотелось бы большего: указать интерпретатору, что строковая переменная является куском кода на AHK, который нужно выполнить.

Господа! Можно такое реализовать на языке программирования "AutoHotKey"?

21

Re: AHK: eval() hotstrings

Нельзя.

22

Re: AHK: eval() hotstrings

Как вариант -  в процессе работы скрипта вписывать нужные строки автозамены в файл скрипта и тут же перезапускать его.
В случае со скомпилированным скриптом - прописать в коде скрипта файл-Include и вписывать новый код в Include-файл.

23

Re: AHK: eval() hotstrings

ypppu пишет:

Как вариант -  в процессе работы скрипта вписывать нужные строки автозамены в файл скрипта и тут же перезапускать его.

Спасибо за вариант, только я хотел бы "править код на лету" без необходимости перезапускать программу с самого начала


ypppu пишет:

В случае со скомпилированным скриптом - прописать в коде скрипта файл-Include и вписывать новый код в Include-файл.

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

24

Re: AHK: eval() hotstrings

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

На форуме имеются примеры записи в память процесса и поиска в памяти процесса. Можно попробовать сделать в конце скрипта метку, например Dyn_Proc:<много пробелов для выделения памяти>, найти начало пустого места и динамически менять его на нужный код, затем вызывать на исполнение командой GoSub Dyn_proc.

По крайней мере, так должно работать в теории.

25

Re: AHK: eval() hotstrings

Irbis пишет:

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

Спасибо за ответ.
Это очень существенная информация для моих целей.
И я раньше этого не знал.
Но при компиляции в этот экзешник и тексты инклудов запихиваются.Так?
Так что выше предложенный вариант с инклудами ещё одного уважаемого участника тут не прокатит?
Потому что после того как я изменю инклуд мне придётся заново компилить весь проект.

26

Re: AHK: eval() hotstrings

Irbis пишет:

На форуме имеются примеры записи в память процесса и поиска в памяти процесса. Можно попробовать сделать в конце скрипта метку, например Dyn_Proc:<много пробелов для выделения памяти>, найти начало пустого места и динамически менять его на нужный код, затем вызывать на исполнение командой GoSub Dyn_proc.

По крайней мере, так должно работать в теории.

Огромное спасибо.
Вы предложили самый реальный вариант решения моей задачи.
Ещё бы как-то научиться сохранять по завершении работы программы изменившийся код в оперативной памяти на диск - было бы вообще круто.
Т.е. получился бы самомодифицирующийся экзешник

27

Re: AHK: eval() hotstrings

Тоже не понял идею с Include-файлом, т.к. после его изменения необходимо все равно пересобрать exe-файл.

28

Re: AHK: eval() hotstrings

Да-с, память имеет свойство искажаться. Извините, что ввёл в заблуждение с Include в случае со скомпилированным скриптом.