I'm trying to make a macro program with python 3.7 on Windows10
I want to send keyboard/mouse inputs to any specific target window while the target window keep inactivated(minimized or background)
pyautogui seems to not be able to do that (If I miss something let me know plz)
pywinauto can send inputs to specific target window but it always make the target window activate.
Is there any way keeping target window inactivated????
import pywinauto
app = pywinauto.application.Application().connect(best_match='123 - Notepad', top_level_only=False, visible_only=False)
form = app.window(title_re='123 - Notepad')
for i in range(1, 10):
form.type_keys("12e12e21e")
I found the answer!!!!
app = Application(backend="win32").connect(process=12345)
form = app.window(title_re="windowtitle")
form.send_keystrokes("1234567")
Remote Execution Guide -> Tricks to run automation on a locked machine
Related
I wanted to create a metin2 bot, nothing complicated. I am new into that so i just started to look for tutorials on youtube to find something that would lead me to world of coding, how does it work, what language is used to write it ect. So I found a tutorial on youtube about open CV Learn Code By Gaming - OpenCV and thought that's awesome thing to start with.
I got to the point where I can easily detect the names of monsters/metins and wont have any problems in finding the right points to click. After detection started working I thought about automating clicking on the window to farm some items etc. Simple things like clicking e.g 50 pixels below the name to auto attack worked just fine but the problem was that I wanted to make more bots to maximalize farming. So when i started to add more clients I got a problem where e.g you have to hold down SPACE in one window to attack from horse and click on another window which was stopping attacking from horse. So I thought about finding some code that can basically send message directly to window without controlling a mouse or keyboard so you can run multiple bots in one time and each will do perfect meanwhile you can do anything else on pc because your mouse and keyboard aren't used.
Let's start from code I found and none worked for windows in background (even with administrator privileges). Pyautogui doesn't work in background (window has to be in foreground to be clicked on and it controls mouse so there is no point in using that.
From that code I learned that I need to find "window ID" to connect to it and send messages. When i print hWnd it shows the numbers in Terminal and code passes without any fails but does nothing except printing the window ID ( Parent Handle ). Ofc I pip installed pywin32
import win32gui
import win32api
import win32con
def click(x, y):
hWnd = win32gui.FindWindow(None, "Client")
print(hWnd)
lParam = win32api.MAKELONG(x, y)
win32api.SendMessage(hWnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lParam)
win32api.SendMessage(hWnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, lParam)
click(100, 100)
Than i found another code that looked similar but used different function so first i used
wdname = 'Client'
hwnd = win32gui.FindWindow(None, wdname) # parent handle
print(hwnd)
Which printed me a window ID that i used in parameters in function
def control_click(x, y, handle, button):
l_param = win32api.MAKELONG(x, y)
if button == 'left':
win32gui.PostMessage(handle, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param)
win32gui.PostMessage(handle, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, l_param)
elif button == 'right':
win32gui.PostMessage(handle, win32con.WM_RBUTTONDOWN, 0, l_param)
win32gui.PostMessage(handle, win32con.WM_RBUTTONUP, 0, l_param)
control_click(200, 200, 329570, button ='left')
But it still did nothing but code passed clear
Anyone have any ideas about how to make clicks/keyboard clicks in python on window in background without taking controll of mouse/keyboard? If you have any experience in automating and know better ways to create automation for clicking ect. and want to share it please do. If that can be done in another programming language also share your toughts about that of course if you want to.
Windows 10 x64
Python used: 3.9.2
All codes i found in topics were out of date that s why i am asking for help there. Thanks in advance :)
app = Application(backend="uia").start("program.exe")
I am using pywinauto to do some tasks indefinitely. However, occasionally, I need to restart the script for some external reasons. When this happens, I would like to keep the created applications open. How can I do this? I noticed if the python script errors out, the applications will stay open. But if I exit the script manually, the windows will close. So there must be some way to accomplish this.
I think pywinauto's Application.start cannot do the work. You can try:
pid = os.spawnl(os.P_NOWAIT, "program.exe")
app = Application().connect(process=pid)
os.spawnl is considered deprecated. Use subprocess module.
Combining the answer in Run a program from python, and have it continue to run after the script is killed and pywinauto official doc, you can do this:
subprocess.Popen(
['your_program', 'with args'],
# These will make sure the desktop program will alive even when shell session terminates.
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP, shell=True
)
desktop = Desktop(backend="uia")
main_win = desktop.window(title="program's window title", control_type="Window")
Why not use system command:
#Use multiple thread to avoid block of system function
import _thread as qd
import os
qd.start_new_thread(os.system,('notepad',))
from pywinauto import Application
#connect pywinauto with application via title regular expression
win=Application(backend='uia').connect(title_re='.*Notepad.*')
Then you use pywinauto to connect application via title?
i am using a tkinter Text widget to display the content of gerber-code files.
the program runs on a raspberry pi and send code over serial to a machine one line of text at at time.
i set the current active line as follows:
class TextEditor(tkinter.Text):
def __init__(self, tkRoot):
...
self.tag_configure("activeLine", background="#87e8ed")# set the colour used for activeLine
def setLine(self, lineNumber):
self.tag_remove("activeLine", "1.0", "end")
self.tag_add("activeLine", str(lineNumber)+".0 linestart", str(lineNumber)+".0 lineend+1c")
def getLine(self):
pass # need to return the activeLine line number
there should only ever be one line at a time highlighted with "activeLine" so the first instance would be fine.
i could store a variable in the call to setLine and read it back in getLine but i would prefer not to as any edits to the text it could go out of sink
i notice using IDLE that the debugger uses what looks the same principle as i am trying to achieve here to set breakpoints, is it possible and if so where would i start looking for the IDLE source code to look into how it is achieved there, i am currently writing this on a Ubuntu 18.04 desktop i would like to no best ways to search IDLE source from
any help would be greatly appreciated, i am quite new to python and tkinter as i am generally a windows dot.net programmer but i am now learning to use Linux
i have now found an answer to my own question
listing all the functions of the text widget that start with "tag_" like this:
d = dir(self.tkRoot.text)
for dv in d:
s = str(dv)
if s.startswith("tag_"):
print(dv)
i found the method "tag_ranges(name)" that returns me this
(<textindex object: '5.0'>, <textindex object: '6.0'>)
at the time of calling the current line was 5
I need to write an application that basically focuses on a given Windows window title and copy-pastes data in a notepad. I've managed to achieve it with pygetwindow and pyautogui, but it's buggy:
import pygetwindow as gw
import pyautogui
# extract all titles and filter to specific one
all_titles = gw.getAllTitles()
titles = [title for title in all_titles if 'title' in title]
window = gw.getWindowsWithTitle(titles[0])[0].activate()
pyautogui.hotkey('ctrl', 'a')
pyautogui.hotkey('ctrl', 'c')
Using Spyder, I ocasionally get the following error when activating:
PyGetWindowException: Error code from Windows: 126 - The specified module could not be found.
Additionally, I would be interested in doing this process without affecting the user working on the machine. Activate basically makes the window pop to front. Moreover, it would be better to not be OS dependant, but I haven't found anything yet.
I've tried pywinauto but the SetFocus() method doesn't work (it's buggy, documented).
Is there any other method which would make the whole process invisible and easier?
Not sure if this will help
I am using pywinauto to set_focus
import pywinauto
import pygetwindow as gw
def focus_to_window(window_title=None):
window = gw.getWindowsWithTitle(window_title)[0]
if not window.isActive:
pywinauto.application.Application().connect(handle=window._hWnd).top_window().set_focus()
Good Afternoon :) Having a problem with my Python3 Gtk3 application and Selenium WebDriver (ChromeDriver). Also, using Linux if it matters.
Basically, the user presses a button to start the Selenium webdriver automation and then as the automation process is going, it 'SHOULD' give feedback to the user in the GUI (See Content.content_liststore.append(list(item)) and LogBox.log_text_buffer).
However, it's not adding anything into the content_liststore until after fb_driver.close() is done. In the meantime, the Gtk window just "hangs".
Now, I've been looking into multithreading in hopes of the GUI being responsive to this feedback but I've also been reading that Selenium doesn't like multithreading (but I presume thats running multiple browsers/tabs (which this is not)).
So, my question is; Is multithreading the go-to fix for getting this to work?
# ELSE IF, FACEBOOK COOKIES DO NOT EXIST, PROCEED TO LOGIN PAGE
elif os.stat('facebook_cookies').st_size == 0:
while True:
try: # look for element, if not found, refresh the webpage
assert "Facebook" in fb_driver.title
login_elem = fb_driver.find_element_by_id("m_login_email")
login_elem.send_keys(facebook_username)
login_elem = fb_driver.find_element_by_id("m_login_password")
login_elem.send_keys(facebook_password)
login_elem.send_keys(Keys.RETURN)
except ElementNotVisibleException:
fb_driver.refresh()
StatusBar.status_bar.push(StatusBar.context_id, "m_login_password element not found, trying again...")
ProblemsLog.text_buffer.set_text("Facebook has hidden the password field, refreshing page...")
else:
query_elem = fb_driver.find_element_by_name("query")
query_elem.send_keys(target)
query_elem.send_keys(Keys.RETURN)
break
m_facebook_url_remove = "query="
m_facebook_url = fb_driver.current_url.split(m_facebook_url_remove, 1)[1] # Remove string before "query="
facebook_url = "https://www.facebook.com/search/top/?q=" + m_facebook_url # Merge left-over string with the desktop url
StatusBar.status_bar.push(StatusBar.context_id, "Facebook elements found")
fb_title = fb_driver.title
fb_contents = [(target_name.title(), "Facebook", facebook_url)]
for item in fb_contents:
Content.content_liststore.append(list(item))
#progress_bar.set_fraction(0.10)
LogBox.log_text_buffer.set_text("Facebook Search Complete")
with open('facebook_cookies', 'wb') as filehandler:
pickle.dump(fb_driver.get_cookies(), filehandler)
fb_driver.close()
I've considered it not working because of the 'while' loop, but another piece of code doesn't have a loop and does the exact same thing, it waits for Selenium to finish before adding content to the GUI.
Additionally, the user can select multiple websites to do this with, so the application can first go to Facebook (do it's business then close), go to LinkedIn (do it's business then close) and so fourth. And it still waits for all the Selenium code to finish before adding anything to the Gtk GUI.
I really hope that makes sense! Thank you :)
Your`s question is the answer you are lookig for. Take a read here https://wiki.gnome.org/Projects/PyGObject/Threading