首页 > 解决方案 > 我的 AutoHotKey 脚本如何相应地启动批处理脚本?

问题描述

该脚本应该将我从 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
}

我认为我的括号/函数/布尔定义有问题。你发现错误了吗?

标签: virtual-machineautohotkeyrdp

解决方案


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

Pause::vmStart()
return

runVM := false
linux := false

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

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

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

将它们定义为全局意味着您引用了在函数范围之外找到的变量,并且其值将存储在那里。要将变量定义为全局变量,您可以让函数的第一行执行以下操作:

vmStart()
{
    global runVM, linux
    ...

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

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

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

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

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

当然,当您有这样的小脚本时,无论您使用什么方法都没有区别。即使我承认有时在我的个人脚本上使用超级全局,只是因为不必担心范围非常方便。

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

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

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
}

推荐阅读