Как мой скрипт AutoHotKey может запускать пакетные сценарии соответственно? - PullRequest
0 голосов
/ 29 января 2020

Этот сценарий должен переключить меня с Windows на Linux (ВМ) и наоборот:

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
}
  • Когда я нахожусь в Windows, он должен активировать мой Сначала окно RDP (что работает нормально).
  • Когда я нахожусь в Windows и виртуальная машина не была запущена с PS.cmd, то она должна запустить его (что также работает и занимает около 18 сек c )
  • Использование ^! {CtrlBreak} является нормальным переключателем, который также работает.

Я думаю, что что-то не так с моим определением в скобках / функции / булево. Вы нашли ошибку?

1 Ответ

4 голосов
/ 29 января 2020

Имеется несколько проблем, но важна только одна.
Во-первых, ваши определения переменных представляют собой недоступный код.

Pause::vmStart()
return

runVM := false
linux := false

Выполнение кода останавливается на первой встреченной горячей клавише.
В Кроме того, у вас также есть Return, что также остановит выполнение кода. Таким образом, вы действительно убедитесь, что выполнение кода никогда не достигнет определения переменных, ха-ха.
К счастью, AHK - это супер-прощение, и если вы ссылаетесь на любую переменную, которая еще не была объявлена, она создается со значением по умолчанию nothing , что также оценивается как false .

Так что это не было реальной проблемой, но все же что-то, что требует исправления. Переместите определения, чтобы они были выше вашей горячей клавиши, или просто удалите их, они не нужны из-за того, как простит AHK, как объяснено выше.
Тогда к следующей проблеме - переменная область действия.

В этом Область действия переменных, на которые вы ссылаетесь, не существует, и они создаются и освобождаются при каждом запуске функции.
У вас есть несколько вариантов, которые вы можете сделать. Вы можете определить переменные как global , stati c или super global (super global - это плохая практика и не рекомендуется).

Определение их как глобальных означает, что вы ссылаетесь на переменную, которая находится вне области действия функции, и ее значение будет храниться там. Чтобы определить переменные как глобальные, вы должны сделать так, чтобы первая строка (ы) вашей функции выполнялась следующим образом:

vmStart()
{
    global runVM, linux
    ...

Или вы могли бы просто сделать первую строку функции не более чем ключевым словом global, и это означает, что функция предполагает, что все переменные являются глобальными.

Чтобы определить переменные как stati c, вы должны сделать то же самое, что и для global (с ключевым словом static). Определение их как stati c означает, что они не освобождаются после завершения функции. Поэтому в следующий раз, когда вы вызовете функцию, их значение будет тем, которое вы в последний раз установили в функции.

Чтобы определить их как суперглобальные, вы должны определить переменные вне функции (в самой верхней части ваш сценарий) с ключевым словом global следующим образом:

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

Это будет означать, что любая область видимости, где бы ни пытались ссылаться на переменную по этому имени, будет использовать вашу суперглобальную переменную. Это плохая практика и может быть опасно, особенно если вы используете внешние библиотеки. Не было бы слишком сложно случайно что-то сломать.

Конечно, когда у вас есть такой маленький сценарий, не имеет значения, какой метод вы используете. Даже я признаюсь, что иногда использую super global в своих личных сценариях, просто потому, что не нужно беспокоиться о границах.

Если вы хотите услышать мою рекомендацию, я бы сказал go для stati c переменные.
Это в значительной степени точно предназначено для того, что вы здесь делаете.

Вот ваш готовый продукт (с некоторыми различными изменениями) на случай, если я не объяснил что-то достаточно хорошо:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...