pythonwinapipywin32win32guibluestacks

Send input to Bluestacks app running in background


I'm trying to build simple bot that will periodically send invites to the guild in game chat. Developing scripts in bluestacks was an easy part, now I'm trying to develop a simple python program that will trigger those scripts by sending input to bluestacks. Using Spy++ I figured out that app contains multiple windows and has the following structure:

[-] Window 00010912 "InviteBot" HwndWrapper[Bluestacks.exe;;<a long hex code>]
    [-] Window 00030932 "BlueStacks Android PluginAndroid_1" WindowsForms10.Window.8.app.0.1<hex part>
        [] Window 000409D0 "" WindowsForms10.EDIT.app.0.1<same hex part as above>
        [] Window 0002092E "_ctl.Window" BlueStacksApp

Using 'Find Window' functionality of Spy++ pointed me to the last layer - '_ctl.Window'.

After googling I've found 2 approaches (on StackOverflow) to send input to the app, first one:

wsh = comclt.Dispatch("WScript.Shell")
wsh.AppActivate("InviteBot")  # select another application
wsh.SendKeys("q")  # send the keys you want

works good, but activates the window which makes diffcult to work on PC when it sends an input, so I needed another approach:

def enum_handler(hwnd, lparam):
    if win32gui.IsWindowVisible(hwnd):
        if 'InviteBot' in win32gui.GetWindowText(hwnd):
            invite_bot_handle = hwnd
            print("invite_bot_handle: {}".format(invite_bot_handle))
            print(win32gui.GetWindowText(invite_bot_handle))
            win32gui.PostMessage(invite_bot_handle, win32con.WM_CHAR, 'q', 0)
            win32gui.PostMessage(invite_bot_handle, win32con.WM_KEYDOWN, win32con.VK_F1, 0)
            win32gui.PostMessage(invite_bot_handle, win32con.WM_KEYUP, win32con.VK_F1, 0)

            blue_stacks_app_handle = win32gui.FindWindowEx(invite_bot_handle, None, None, "BlueStacks Android PluginAndroid_1")
            print("blue_stacks_app_handle: {}".format(blue_stacks_app_handle))
            print(win32gui.GetWindowText(blue_stacks_app_handle))
            win32gui.PostMessage(blue_stacks_app_handle, win32con.WM_CHAR, 'q', 0)
            win32gui.PostMessage(blue_stacks_app_handle, win32con.WM_KEYDOWN, win32con.VK_F1, 0)
            win32gui.PostMessage(blue_stacks_app_handle, win32con.WM_KEYUP, win32con.VK_F1, 0)

            target_window_handle = win32gui.FindWindowEx(blue_stacks_app_handle, None, None, "_ctl.Window")
            print("blue_stacks_app_handle: {}".format(target_window_handle))
            print(win32gui.GetWindowText(target_window_handle))
            win32gui.PostMessage(target_window_handle, win32con.WM_CHAR, 'q', 0)
            win32gui.PostMessage(target_window_handle, win32con.WM_KEYDOWN, win32con.VK_F1, 0)
            win32gui.PostMessage(target_window_handle, win32con.WM_KEYUP, win32con.VK_F1, 0)


win32gui.EnumWindows(enum_handler, None)

I tried sending various types of input to all layers of this heirarchy, but seems those messages are not receieved.

When I tried to call win32gui.MoveWindow(TargetWindowHandle, 0, 0, 760, 500, True) just to make sure that window handles are the ones I'm looking for it worked fine. Calling this for the top-level window moved whole BlueStacks app. For other layers it is just caused window to look odd. So the handle values should be correct.

Example of output (executed from PyCharm)

>>> runfile('D:/Codes/DeffclanRose/BlueStackActions.py', wdir='D:/Codes/DeffclanRose')
invite_bot_handle: 67858
InviteBot
blue_stacks_app_handle: 198962
BlueStacks Android PluginAndroid_1
blue_stacks_app_handle: 133422
_ctl.Window

Edit: What I am looking for is a way to send input to an app, running in a background.


Solution

  • Bluestack game control is disabled whenever the window is inactive that's why inputs are not working inside the game. I have the same problem and I fixed it by using this WM_ACTIVATE before sending inputs: I found it here: https://stackoverflow.com/a/45496600/11915042

    Here is my sample code:

    import win32gui, win32api, win32con
    import time
    
    hwnd = win32gui.FindWindow(None, 'BlueStacks')
    hwndChild = win32gui.GetWindow(hwnd, win32con.GW_CHILD)
    hwndChild2 = win32gui.GetWindow(hwndChild, win32con.GW_CHILD)
     
    win32gui.SendMessage(hwnd, win32con.WM_ACTIVATE, win32con.WA_CLICKACTIVE, 0)
    
    time.sleep(1) # Without this delay, inputs are not executing in my case
    
    win32api.PostMessage(hwndChild2, win32con.WM_KEYDOWN, win32con.VK_F1, 0)
    time.sleep(.5)
    win32api.PostMessage(hwndChild2, win32con.WM_KEYUP, win32con.VK_F1, 0)