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

Pat*_*ode 0 rdp autohotkey virtual-machine

这个脚本应该让我从 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
}
Run Code Online (Sandbox Code Playgroud)
  • 当我在 Windows 中时,它需要先激活我的 RDP 窗口(工作正常)。
  • 当我在 Windows 中并且 VM 没有用 PS.cmd 启动时,它应该启动它(这也有效,大约需要 18 秒)
  • 使用 ^!{CtrlBreak} 是正常的开关也可以使用。

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

0x4*_*64e 5

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

Pause::vmStart()
return

runVM := false
linux := false
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

vmStart()
{
    global runVM, linux
    ...
Run Code Online (Sandbox Code Playgroud)

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

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

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

global runVM := false
global linux := false
Pause::vmStart()
...
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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
}
Run Code Online (Sandbox Code Playgroud)