AHK:管理多个脚本

时间:2013-08-09 15:34:55

标签: automation autohotkey

我有很多脚本。我希望能够在脚本中以1为单位管理它们。 我想要的是主脚本将激活某个脚本,然后当辅助脚本完成时,它会向主脚本返回一个值。之后,主脚本调用另一个辅助脚本等...

有没有正确的方法呢?

更精确的问题:

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

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

3 个答案:

答案 0 :(得分:3)

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

沟通的最佳选择是使用OnMessage

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

; 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.
}

答案 1 :(得分:2)

好吧,我不确定你为什么要让一个脚本运行另一个脚本......但是这里有一些其他的方法:

将脚本包含在另一个

但是,你知道你可以在另一个脚本里面include一个脚本,对吧?也就是说,您可以在主脚本中使用其他脚本函数。

确保加载了特定的脚本

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

;make sure core.ahk is loaded since it is required
#include c:\ahk\core.ahk

你不必担心它被包含多次(除非你需要它)因为:

  

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

现在,当我在file.ahk中加入main.ahk时,我确信使用file.ahk所需的core.ahk函数没有任何问题。即使我再次在core.ahk中包含main.ahk,也不用担心(除非它包含子程序而不仅仅是函数 - 在这种情况下它们会在包含它们的位置运行,所以最好不要把子程序放在你的ahk库中。)

在脚本上使用好的'RUN

除此之外,您知道您始终可以使用run命令启动ahk脚本。你不必做那些花哨的WM_SENDMESSAGE东西。

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

两个脚本之间相互通信的另一种方式是脚本#1保持打开一个隐藏的GUI窗口,该窗口具有编辑框和提交按钮。永远不会显示此窗口。现在,脚本#2搜索该消息框,使用send将字符串放入编辑框,然后按住Control键单击以按下提交按钮。现在脚本#1刚收到来自脚本#2的输入。如果你在两个脚本中都放置了hwnd值,那么你甚至不必寻找窗口(所以他们已经提前知道了)。这就像一个魅力。

判断脚本是否已完成

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

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

答案 2 :(得分:0)

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

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

最后,考虑使用一个函数,因为这可能是最佳实践"为了你想做什么。由于函数可以执行脚本可以执行的任何操作,因此您可以将其传递给数组以在数组参数上使用或使用ByRef进行操作。这意味着您在编写函数时不必编写一堆参数,并且一旦函数完成,变量将自动释放内存。您甚至可以在单独的文件中编写函数,并使用#Include在脚本中使用它们。