Search code examples
pythoninputblock

Python Block Keyboard / Mouse Input


i am currently trying to write a short script that will rickroll (open a youtube link) while the user is watching and can't interfere. I have managed to open insert the link slowly letter by letter and am now trying to block user inputs. I have tried using the ctypes import to block all inputs, run the script and then unblock again, but it somehow won't block the input. I'm just receiving my RuntimeError message. How do i fix it, so the inputs get blocked? Thanks in advance! Heres the code:

import subprocess
import pyautogui
import time
import ctypes
from ctypes import wintypes

BlockInput = ctypes.windll.user32.BlockInput
BlockInput.argtypes = [wintypes.BOOL]
BlockInput.restype = wintypes.BOOL

blocked = BlockInput(True)

if blocked:
    try:
        subprocess.Popen(["C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",])
        time.sleep(3)
        pyautogui.write('www.youtube.com/watch?v=DLzxrzFCyOs', interval= 0.5)
        pyautogui.hotkey('enter')
    finally:
        unblocked = BlockInput(False)
else:
    raise RuntimeError('Input is already blocked by another thread')

Solution

  • You can use the keyboard module to block all keyboard inputs and the mouse module to constantly move the mouse, preventing the user from moving it.

    See these links for more details:

    https://github.com/boppreh/keyboard

    https://github.com/boppreh/mouse

    This blocks all the keys on the keyboard (the 150 is large enough to ensure all keys are blocked).

    #### Blocking Keyboard ####
    import keyboard
    
    #blocks all keys of keyboard
    for i in range(150):
        keyboard.block_key(i)
    

    This effectively blocks mouse-movement by constantly moving the mouse to position (1,0).

    #### Blocking Mouse-movement ####
    import threading
    import mouse
    import time
    
    global executing
    executing = True
    
    def move_mouse():
        #until executing is False, move mouse to (1,0)
        global executing
        while executing:
            mouse.move(1,0, absolute=True, duration=0)
    
    def stop_infinite_mouse_control():
        #stops infinite control of mouse after 10 seconds if program fails to execute
        global executing
        time.sleep(10)
        executing = False
    
    threading.Thread(target=move_mouse).start()
    
    threading.Thread(target=stop_infinite_mouse_control).start()
    #^failsafe^
    

    And then your original code here (the if statement and try/catch block are no longer necessary).

    #### opening the video ####
    import subprocess
    import pyautogui
    import time
    
    subprocess.Popen(["C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",])
    time.sleep(3)
    pyautogui.write('www.youtube.com/watch?v=DLzxrzFCyOs', interval = 0.5)
    pyautogui.hotkey('enter')
    
    
    #### stops moving mouse to (1,0) after video has been opened
    executing = False
    
    

    Just a few notes:

    1. The mouse-moving is hard to stop from outside of the program (it's basically impossible to close the program when it is executing, especially as the keyboard is also being blocked), that's why I put in the failsafe, which stops moving the mouse to (1,0) after 10 seconds.
    2. (On Windows) Control-Alt-Delete does allow Task Manager to be opened and then the program can be force-stopped from there.
    3. This doesn't stop the user from clicking the mouse, which can sometimes prevent the YouTube link from being typed in full (i.e. a new tab can be opened)

    See a full version of the code here:

    https://pastebin.com/WUygDqbG