我的 AutoHotKey 脚本如何相应地启动批处理脚本? [英] How can my AutoHotKey script launch batch scripts accordingly?

查看:48
本文介绍了我的 AutoHotKey 脚本如何相应地启动批处理脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Pause::vmStart()返回运行VM:=假linux := 假vmStart(){如果 (!runVM 和 !linux) {运行,C:Userspatrickdev-vmPS.cmd运行VM := true睡眠,18000}如果 (!linux 和 !WinExist("DevVM - 127.0.0.1:23389 - RDP")) {运行,C:Userspatrickdev-vmRDP.cmd}如果(!linux){WinShow,DevVM - 127.0.0.1:23389 - RDPWinActivate,DevVM - 127.0.0.1:23389 - RDP}发送 ^!{CtrlBreak}linux := !linux}

  • 当我在 Windows 中时,它需要先激活我的 RDP 窗口(什么有效很好).
  • 当我在 Windows 中并且 VM 没有使用 PS.cmd 启动时,它应该启动它(这也能正常工作,大约需要 18 秒)
  • 使用 ^!{CtrlBreak} 是正常的开关也可以使用.

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

解决方案

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

Pause::vmStart()返回运行VM:=假linux := 假

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

所以这不是实际问题,但仍然需要修复.将定义移到热键上方,或者直接删除它们,因为 AHK 的宽容度很高,所以不需要它们,如上所述.
然后进入下一个问题,变量作用域.

在该函数的作用域中,您引用的变量不存在,并且每次运行该函数时都会创建和释放它们.
你有几个选项可以做.您可以将变量定义为 globalstatic超级全局(超级全局是不好的做法,不推荐).

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

vmStart(){全局运行VM,Linux...

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

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

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

全局运行VM := false全球 linux := false暂停::vmStart()...

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

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

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

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

Pause::vmStart();这里的'return'对我们没有任何作用,被删除了vmStart(){;使用static关键字使函数假设;所有变量都是静态的,甚至也跳过;声明变量,不需要,因为 AHK 是多么宽容静止的;去掉 if 语句中的and"关键字;那是遗留语法,天哪,这不是 2005 年如果 (!runVM && !linux) {运行,C:Userspatrickdev-vmPS.cmd运行VM := true睡眠,18000};删除大括号,单行语句不需要它们;当然只是个人喜好如果 (!linux && !WinExist("DevVM - 127.0.0.1:23389 - RDP"))运行,C:Userspatrickdev-vmRDP.cmd如果(!linux){WinShow,DevVM - 127.0.0.1:23389 - RDPWinActivate,DevVM - 127.0.0.1:23389 - RDP};切换到SendInput,更快更可靠发送输入,^!{CtrlBreak}linux := !linux}

This script is supposed to switch me from Windows to Linux(VM) and vice versa:

Pause::vmStart()
return

runVM := false
linux := false

vmStart()
{
    If (!runVM and !linux) {
        Run, C:Userspatrickdev-vmPS.cmd
        runVM := true
        sleep, 18000
    }
    If (!linux and !WinExist("DevVM - 127.0.0.1:23389 - RDP")) {
        Run, C:Userspatrickdev-vmRDP.cmd
    }
    if (!linux) {
        WinShow, DevVM - 127.0.0.1:23389 - RDP
        WinActivate, DevVM - 127.0.0.1:23389 - RDP
    }
    Send ^!{CtrlBreak}
    linux := !linux
}

  • When I am in Windows, it needs to activate my RDP window first (what works fine).
  • When I am in Windows and the VM was not started with PS.cmd, then it should launch it (what also works and takes about 18 sec)
  • Using ^!{CtrlBreak} is the normal switch that also works.

I think that there is something wrong with my brackets/function/boolean definition. Do you find the mistake?

解决方案

Has a few problems, but just one that matters.
Firstly, your variable definitions are unreachable code.

Pause::vmStart()
return

runVM := false
linux := false

Code execution stops at the first hotkey that is met.
In addition you also have a Return in there, which would also stop code execution. So you really are making sure code execution will never reach the variable definitions haha.
Luckily AHK is super forgiving and if you reference any variable that hasn't been declared yet, it's created with the default value of nothing, which also evaluates to false.

So that wasn't the actual problem, but still something that needs fixing. Move the definitions to be above your hotkey, or just remove them, they're not needed due to how forgiving AHK is, as explained above.
Then onto the next problem, variable scope.

In that function's scope the variables you reference don't exist, and they're created and freed every time you run the function.
You have a few options you can do. You can either define the variables as global, static, or super global (super global is bad practice and not recommended).

Defining them as global means you reference a variable that's found outside of the function's scope and its value will be stored there. To define the variables as global, you'd make the first line(s) of your function do that like this:

vmStart()
{
    global runVM, linux
    ...

Or you could just make the first line of function be nothing but the keyword global, and that means the function assumes all variables are global.

To define the variables as static, you'd do the same as for global (with the keyword static). Defining them as static basically means they aren't freed after the function completes its execution. So next time you call the function their value is what you last set it to be in the function.

To define them as super global, you'd define the variables outside of the function (at the very top of your script) with the keyword global like this:

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

This would mean any scope anywhere that tried to reference a variable by that name would use your super global variable. This is bad practice and can be dangerous to do, especially if you use external libraries. Wouldn't be too hard to accidentally break something.

Of course when you have a little script like that, is makes no difference whatsoever what method you use. Even I confess to sometimes using super global on my personal scripts, just because it's quite convenient to not have to worry about scopes.

If you'd like to hear my recommendation, I'd say go for static variables.
It's pretty much exactly intended for what you're doing here.

Here's your finished product (with some miscellaneous changes) in case I didn't explain something well enough:

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:Userspatrickdev-vmPS.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:Userspatrickdev-vmRDP.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
}

这篇关于我的 AutoHotKey 脚本如何相应地启动批处理脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆