Automation AHK:管理多个脚本

Automation AHK:管理多个脚本,automation,autohotkey,Automation,Autohotkey,我有很多剧本。我想能够管理他们在脚本1所有。 我想要的是,主脚本将激活某个脚本,然后当次脚本完成时,它将向主脚本返回一个值。之后,主脚本调用另一个辅助脚本,等等 有没有合适的方法 更确切的问题是: 是否可以从另一个脚本AHK激活一个AHK脚本 目前,为了检测辅助脚本是否完成,我目前使用的方法是,在辅助脚本结束之前,按下主脚本将检测到的一组键。一旦检测到,它将主脚本变量增加1,这将触发下一个脚本的激活。有没有更好的方法来实现这一点 主脚本可以使用RunWait调用其他脚本。然后,脚本可以在终止自身

我有很多剧本。我想能够管理他们在脚本1所有。 我想要的是,主脚本将激活某个脚本,然后当次脚本完成时,它将向主脚本返回一个值。之后,主脚本调用另一个辅助脚本,等等

有没有合适的方法

更确切的问题是:

是否可以从另一个脚本AHK激活一个AHK脚本

目前,为了检测辅助脚本是否完成,我目前使用的方法是,在辅助脚本结束之前,按下主脚本将检测到的一组键。一旦检测到,它将主脚本变量增加1,这将触发下一个脚本的激活。有没有更好的方法来实现这一点


主脚本可以使用RunWait调用其他脚本。然后,脚本可以在终止自身之前进行通信

沟通的最佳选择是使用

以下是文档中的工作示例:

; Example: Send a string of any length from one script to another.  This is a working example.
; To use it, save and run both of the following scripts then press Win+Space to show an
; InputBox that will prompt you to type in a string.

; Save the following script as "Receiver.ahk" then launch it:
#SingleInstance
OnMessage(0x4a, "Receive_WM_COPYDATA")  ; 0x4a is WM_COPYDATA
return

Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 2*A_PtrSize)  ; Retrieves the CopyDataStruct's lpData member.
    CopyOfData := StrGet(StringAddress)  ; Copy the string out of the structure.
    ; Show it with ToolTip vs. MsgBox so we can return in a timely fashion:
    ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData%
    return true  ; Returning 1 (true) is the traditional way to acknowledge this message.
}

; Save the following script as "Sender.ahk" then launch it.  After that, press the Win+Space hotkey.
TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey

#space::  ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  ; User pressed the Cancel button.
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
    MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
    MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return

Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)  ; Set up the structure's memory area.
    ; First set the structure's cbData member to the size of the string, including its zero terminator:
    SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
    NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)  ; OS requires that this be done.
    NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)  ; Set lpData to point to the string itself.
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%  ; 0x4a is WM_COPYDATA. Must use Send not Post.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}

主脚本可以使用RunWait调用其他脚本。然后,脚本可以在终止自身之前进行通信

沟通的最佳选择是使用

以下是文档中的工作示例:

; Example: Send a string of any length from one script to another.  This is a working example.
; To use it, save and run both of the following scripts then press Win+Space to show an
; InputBox that will prompt you to type in a string.

; Save the following script as "Receiver.ahk" then launch it:
#SingleInstance
OnMessage(0x4a, "Receive_WM_COPYDATA")  ; 0x4a is WM_COPYDATA
return

Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 2*A_PtrSize)  ; Retrieves the CopyDataStruct's lpData member.
    CopyOfData := StrGet(StringAddress)  ; Copy the string out of the structure.
    ; Show it with ToolTip vs. MsgBox so we can return in a timely fashion:
    ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData%
    return true  ; Returning 1 (true) is the traditional way to acknowledge this message.
}

; Save the following script as "Sender.ahk" then launch it.  After that, press the Win+Space hotkey.
TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey

#space::  ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  ; User pressed the Cancel button.
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
    MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
    MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return

Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)  ; Set up the structure's memory area.
    ; First set the structure's cbData member to the size of the string, including its zero terminator:
    SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
    NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)  ; OS requires that this be done.
    NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)  ; Set lpData to point to the string itself.
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%  ; 0x4a is WM_COPYDATA. Must use Send not Post.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}

我不知道你为什么要让一个脚本运行另一个。。。但这里还有一些其他方法:

在另一个脚本中包含脚本

但是,你知道你可以在另一个脚本中包含一个脚本,对吗?也就是说,您可以在主脚本中使用其他脚本函数

确保加载了特定的脚本

我也有很多剧本。有时,我需要确保在使用之前包含一个特定的,所以我把它放在顶部:

;make sure core.ahk is loaded since it is required
#include c:\ahk\core.ahk
您不必担心它被多次收录,除非您需要它,因为:

Include确保文件名只包含一次,即使遇到多个包含项。相比之下,IncludeAgain允许 同一文件的多个包含项,同时与包含项相同 在所有其他方面

现在,当我在main.ahk中包含file.ahk时,我确信使用file.ahk所需的core.ahk函数不会有问题。即使我在main.ahk中再次包含core.ahk,也不必担心,除非它包含子例程而不仅仅是函数——在这种情况下,它们会在包含它们的地方运行,所以最好不要将子例程放在ahk库中

使用好的ole“在脚本上运行”

除此之外,您知道您可以随时使用run命令启动ahk脚本。你不必做那些花哨的WM_SENDMESSAGE之类的事情

使用隐藏GUI在NST脚本之间进行通信

两个脚本之间通信的另一种方式是脚本1保持打开一个隐藏的GUI窗口,该窗口有一个编辑框和一个提交按钮。此窗口将永远不会显示。现在,脚本2查找该消息框,使用send将字符串放入编辑框,然后控制单击以按下submit按钮。现在,脚本1刚刚收到来自脚本2的输入。如果你在两个脚本中都添加了windowshwnd值,那么你甚至不需要搜索窗口,这样他们就可以提前知道。这很有魅力

说明脚本是否已完成

如果使用ahk的run命令,则有一个参数将返回该进程的PID PID=进程ID。您可以使用此PID检查脚本是否正在运行,并可以使用它终止该进程


另外,如果您使用runwait,则使用该命令的脚本将暂停并等待运行的进程完成并关闭,然后再继续。

嗯,我不确定您为什么要让一个脚本运行另一个脚本。。。但这里还有一些其他方法:

在另一个脚本中包含脚本

但是,你知道你可以在另一个脚本中包含一个脚本,对吗?也就是说,您可以在主脚本中使用其他脚本函数

确保加载了特定的脚本

我也有很多剧本。有时,我需要确保在使用之前包含一个特定的,所以我把它放在顶部:

;make sure core.ahk is loaded since it is required
#include c:\ahk\core.ahk
您不必担心它被多次收录,除非您需要它,因为:

Include确保文件名只包含一次,即使遇到多个包含项。相比之下,IncludeAgain允许 同一文件的多个包含项,同时与包含项相同 在所有其他方面

现在,当我在main.ahk中包含file.ahk时,我确信使用file.ahk所需的core.ahk函数不会有问题。即使我在main.ahk中再次包含core.ahk,也不必担心,除非它包含子例程,而不仅仅是函数——在这种情况下,它们会在包含它们的地方运行,所以最好不要将子例程放在你的ahk中 图书馆

使用好的ole“在脚本上运行”

除此之外,您知道您可以随时使用run命令启动ahk脚本。你不必做那些花哨的WM_SENDMESSAGE之类的事情

使用隐藏GUI在NST脚本之间进行通信

两个脚本之间通信的另一种方式是脚本1保持打开一个隐藏的GUI窗口,该窗口有一个编辑框和一个提交按钮。此窗口将永远不会显示。现在,脚本2查找该消息框,使用send将字符串放入编辑框,然后控制单击以按下submit按钮。现在,脚本1刚刚收到来自脚本2的输入。如果你在两个脚本中都添加了windowshwnd值,那么你甚至不需要搜索窗口,这样他们就可以提前知道。这很有魅力

说明脚本是否已完成

如果使用ahk的run命令,则有一个参数将返回该进程的PID PID=进程ID。您可以使用此PID检查脚本是否正在运行,并可以使用它终止该进程


另外,如果您使用runwait,则使用该命令的脚本将暂停并等待运行的进程完成并关闭,然后再继续。

理论上,您也可以在脚本之间使用file对象作为一种stdin/stdout方法,就像使用file对象打开文件时可以将其设置为共享一样

您还可以设置一个环境变量,并将该变量的名称传递给脚本,前提是目标脚本中有设置参数处理,然后目标脚本在关闭时设置环境变量值。使用RunWait和this,您可以发现脚本运行后返回的结果是什么


最后,考虑使用函数,因为这可能是您尝试执行的最佳实践。由于函数可以执行脚本可以执行的任何操作,您可以向它传递一个数组以对其进行操作,或者在数组参数上使用ByRef。这意味着您在编写函数时不必写入大量参数,一旦函数完成,变量将自动释放内存。您甚至可以在单独的文件中编写函数,并使用Include在脚本中使用它们。

理论上,您也可以在脚本之间使用file对象作为一种stdin/stdout方法,就像使用file对象打开文件时可以将其设为共享

您还可以设置一个环境变量,并将该变量的名称传递给脚本,前提是目标脚本中有设置参数处理,然后目标脚本在关闭时设置环境变量值。使用RunWait和this,您可以发现脚本运行后返回的结果是什么


最后,考虑使用函数,因为这可能是您尝试执行的最佳实践。由于函数可以执行脚本可以执行的任何操作,您可以向它传递一个数组以对其进行操作,或者在数组参数上使用ByRef。这意味着您在编写函数时不必写入大量参数,一旦函数完成,变量将自动释放内存。您甚至可以在单独的文件中编写函数,并使用Include在脚本中使用它们。

BGM写道:指令不能属于IF-statement。哦,我想您是对的,我甚至没有意识到这一点。感谢您指出。BGM写道:指令不能属于IF-statement。哦,我想你是对的,我甚至没有意识到这一点。谢谢你指出这一点。