Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotstrings don't work when running alongside another AutoHotkey instance #20

Open
e-r-n-i-e opened this issue Dec 29, 2022 · 4 comments

Comments

@e-r-n-i-e
Copy link

When I start the following script with py -m ahkpy hello-world.py the hotkey [Ctrl+Shift+H] works as expected but both hotstrings don't. When typing hw followed by a space the space is ommited but nothing else happens. When typing wtf followed by a space the space is replaced by Hello World which results in wtfHello World.

hello-world.py:

import ahkpy

CTRL    = '^'
SHIFT   = '+'
WIN     = '#'
ALT     = '!'

print('Ready...')

ahkpy.hotstring("hw", "Hello World")

@ahkpy.hotstring("wtf")
def hello1():
    ahkpy.send("Hello World")

@ahkpy.hotkey(CTRL+SHIFT+"H")
def hello2():
    ahkpy.send("Hello World")

I'm using Autohotkey 1.1.33.10 and Python 3.11.1 on Windows 10.

@e-r-n-i-e
Copy link
Author

It looks like this bug only appears when a normal Autohotkey script with at least one Hotstring is running.

Example script hello1.ahk:

::xxx::Hello World{Enter}

If this script is running, Hotstrings in Autohotkey.py do not work. If this script is suspended (or exited) the do work fine. A normal Autohotkey script without any Hotstring does not cause this error.

I hope this helps to fix this bug.

@Perlence
Copy link
Owner

Hello @e-r-n-i-e!

I believe here's what happens:

  1. A normal AutoHotkey script installs a low-level keyboard hook for the "xxx" hotstring.
  2. The AutoHotkey.py script gets the input mode from the settings, which is "input" by default, and passes it as the SI option to create a hotstring. AutoHotkey then tries to install a low-level keyboard hook but fails and falls back to the SendPlay mode.
  3. The SendPlay mode is known to have no effect at all when UAC is enabled.

You should get the same result if instead of AutoHotkey.py you run the following regular AutoHotkey script alongside hello1.ahk:

:SI:hw::Hello World

Here are a few workarounds you could do:

  1. Try running the AutoHotkey.py script as administrator.
  2. Pass mode="event" to the hotstring call.
  3. Make sure that AutoHotkey.py installs the keyboard hook. This means moving all hotstrings to AutoHotkey.py. Also, check out a few other cases when the hook is installed and move them to AutoHotkey.py.

Other options that require changes in AutoHotkey.py:

  1. Explore running AutoHotkey with UI access. Python's subprocess uses CreateProcess and UIA.exe files cannot be started via CreateProcess due to security restrictions. The AHK docs suggest using ShellExecute.
  2. Explore falling back to SendEvent instead of SendPlay.
  3. ????

@Perlence
Copy link
Owner

BTW I didn't think about using the constants like CTRL = '^'. This is cool, thanks!

@e-r-n-i-e
Copy link
Author

You are right, I get the same result using :SI:hw::Hello World in normal Autohotkey.

But I still would call it a bug, because it does not work as (I) expected. I would expect the following scripts to behave equally even when they are running both at the same time (or with another script using keyboard hooks):

hello.ahk

MsgBox % "Autohotkey " . A_AhkVersion . "`nSendMode = " . A_SendMode
; Output:
;   Autohotkey 1.1.33.10
;   SendMode = Event

SendMode Input
MsgBox % "SendMode = " . A_SendMode
; Output:
;   SendMode = Input

::hwa::Hello World (AHK, mode unset)
; always works, even with multiple scripts using keyboard hooks

:SE:hwae::Hello World (AHK, mode=event)
; always works, even with multiple scripts using keyboard hooks

:SI:hwai::Hello World (AHK, mode=input)
; does NOT work if there is another script using a keyboard hook

:SP:hwap::Hello World (AHK, mode=play)
; NEVER works (tested in Windows Notepad and Visual Studio Code)

hello.py

print("SendMode =", ahkpy.Settings.send_mode)
# Output:
#   SendMode = input

# ::hwa::Hello World (AHK, mode unset)
ahkpy.hotstring("hwp", "Hello World (Python, mode unset)")
# [BUG] SHOULD always work, even with multiple scripts using keyboard hooks, but does NOT

# :SE:hwae::Hello World (AHK, mode=event)
ahkpy.hotstring("hwpe", "Hello World (Python, mode=event)", mode='event')
# [OK] always works, even with multiple scripts using keyboard hooks

# :SI:hwai::Hello World (AHK, mode=input)
ahkpy.hotstring("hwpi", "Hello World (Python, mode=input)", mode='input')
# [OK] does NOT work if there is another script using a keyboard hook

# :SP:hwap::Hello World (AHK, mode=play)
ahkpy.hotstring("hwpp", "Hello World (Python, mode=play)", mode='play')
# [OK] NEVER works (tested in Windows Notepad and Visual Studio Code)

This behaviour is caused by class Hotstring always setting options even if called without options. You might think that this should not be a problem as it will set the default options, but SI is not a default option.

The Autohotkey documentation says:

If none of the above options [SI, SE, SP] are used, the default mode in v1.0.43 and later is SendInput. However, unlike the SI option, SendEvent is used instead of SendPlay when SendInput is unavailable.
Source: https://www.autohotkey.com/docs/v1/Hotstrings.htm#Options

I was able to get the expected behaviour for hotstrings without the SI option with a quick hack. I simply disabled line 311 in hotstring.py:

[...]
        if mode == "input":
            pass #options.append("SI")
[...]

I leave it to you to find the right spot to really fix this. ;-)

@Perlence Perlence changed the title Hotstrings don't work Hotstrings don't work when running alongside another AutoHotkey instance Mar 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants