我的 AutoHotKey 脚本如何相应地启动批处理脚本?

How can my AutoHotKey script launch batch scripts accordingly?

此脚本应该将我从 Windows 切换到 Linux(VM),反之亦然:

Pause::vmStart()
return

runVM := false
linux := false

vmStart()
{
    If (!runVM and !linux) {
        Run, C:\Users\patrick\dev-vm\PS.cmd
        runVM := true
        sleep, 18000
    }
    If (!linux and !WinExist("DevVM - 127.0.0.1:23389 - RDP")) {
        Run, C:\Users\patrick\dev-vm\RDP.cmd
    }
    if (!linux) {
        WinShow, DevVM - 127.0.0.1:23389 - RDP
        WinActivate, DevVM - 127.0.0.1:23389 - RDP
    }
    Send ^!{CtrlBreak}
    linux := !linux
}

我认为我的 brackets/function/boolean 定义有问题。你找到错误了吗?

有一些问题,但只有一个很重要。
首先,您的变量定义是无法访问的代码。

Pause::vmStart()
return

runVM := false
linux := false

代码执行在遇到第一个热键时停止。
此外,您还有一个 Return 在那里,这也会停止代码执行。所以你真的在确保代码执行永远不会到达变量定义哈哈。
幸运的是 AHK 是超级宽容的,如果你引用任何尚未声明的变量,它会使用默认值 nothing 创建,它的计算结果也为 false.

所以这不是真正的问题,但仍然需要修复。将定义移动到您的热键上方,或者只是删除它们,由于 AHK 的宽容程度,因此不需要它们,如上所述。
然后进入下一个问题,变量范围。

在该函数的范围内,您引用​​的变量不存在,并且每次您 运行 函数时都会创建并释放它们。
你有几个选项可以做。您可以将变量定义为 global, static, or super global(超级全局是不好的做法,不推荐)。

将它们定义为全局变量意味着您引用了在函数范围之外找到的变量,并且它的值将存储在那里。要将变量定义为全局变量,您需要让函数的第一行像这样:

vmStart()
{
    global runVM, linux
    ...

或者你可以让函数的第一行只是关键字 global,这意味着函数假定所有变量都是全局变量。

要将变量定义为静态变量,您需要执行与全局变量相同的操作(使用关键字 static)。将它们定义为静态基本上意味着它们在函数完成执行后不会被释放。因此,下次您调用该函数时,它们的值就是您上次在函数中设置的值。

要将它们定义为超级全局变量,您需要使用关键字 global 在函数外部(在脚本的最顶部)定义变量,如下所示:

global runVM := false
global linux := false
Pause::vmStart()
...

这意味着任何试图通过该名称引用变量的范围都将使用您的超级全局变量。这是一种不好的做法,而且这样做可能很危险,尤其是当您使用外部库时。不小心弄坏东西也不会太难。

当然,当你有一个像这样的小脚本时,无论你使用什么方法都没有区别。甚至我承认有时会在我的个人脚本中使用 super global,只是因为不必担心范围非常方便。

如果您想听听我的建议,我建议您使用静态变量。
它几乎完全适合您在这里所做的事情。

这是你的成品(有一些杂项更改)以防我解释得不够好:

Pause::vmStart()
;the 'return' here did nothing for us, removed

vmStart()
{
    ;using the static keyword to make the function assume
    ;all variables are static, and also skipped even 
    ;declaring the variables, not needed due to how forgiving AHK is
    static

    ;got rid of the 'and' keyword in your if statements
    ;that's legacy syntax, big ew, it's not 2005
    If (!runVM && !linux) {
        Run, C:\Users\patrick\dev-vm\PS.cmd
        runVM := true
        sleep, 18000
    }
    ;removed braces, one-liner statments don't need them
    ;just personal preference though, of course
    If (!linux && !WinExist("DevVM - 127.0.0.1:23389 - RDP")) 
        Run, C:\Users\patrick\dev-vm\RDP.cmd
    if (!linux) {
        WinShow, DevVM - 127.0.0.1:23389 - RDP
        WinActivate, DevVM - 127.0.0.1:23389 - RDP
    }
    ;switched to SendInput, it's faster and more reliable
    SendInput, ^!{CtrlBreak}
    linux := !linux
}