PythonScript: How to interact with dialogue boxes?
-
I need to run a ‘Find in Files’ search for multiple directories, and need to search these directories very often. I want to automate this.
All my scripts automate some very specific semi-complex operations, and are deeply tied to the PythonScript functions, so using a different software is not preferable.
I can use this to start a search:
notepad.menuCommand(MENUCOMMAND.SEARCH_FINDINFILES)
But how can I change the directory, and click ‘find all’?
Someone here found how to access search results using some menu scripting magic I don’t understand, so I was wondering if what I’m looking for could also be achieved via PythonScript.
-
need to run a ‘Find in Files’ search for multiple directories, and need to search these directories very often. I want to automate this.
The “problem” with the desired approach you’ve discussed is in its hybridicity (probably not a real word). What I mean is, you want to script part of it, and let Notepad++ handle part of it – and that can cause things to get, well, complicated.
Maybe it would be best to avoid trying to use Notepad++ 's search functions, and go with Python’s or PythonScript’s. For these cases, you wouldn’t get the search output in Notepad++ 's Search results window, though… don’t know if that is a key part of what you want. This route may be another opportunity for using the Little Dialog Wrapper, BTW.
Another possibility for automation is Autohotkey, which I have no experience with (aside from knowing it exists), so I won’t go further with talking about it.
But how can I change the directory, and click ‘find all’?
Well, since you’ve asked a very specific question here, I can give you the answer to it (let me pull something together out of stuff I have), and you can then try it and see if you can work it into whatever bigger picture goal you have in mind.
But, as I said, beyond that things may get “complicated” and you may hit a dead end, and we can’t solve every problem for you here. :-)
-
It turns out that the script HERE is a good framework for the current task. With just a few mods, it can become a demo for an automated press of the button that will do a find-in-files.
I’ll do those mods and then post the new script here…
-
@Alan-Kilborn I actually found pywinauto can do what I wanted:
from pywinauto.application import Application pattern = 'pattern' directory = 'directory' notepad.menuCommand(MENUCOMMAND.SEARCH_FINDINFILES) app = Application().connect(path=r"C:\Program Files\Notepad++\notepad++.exe") dialog = app.FindInFiles app.dialog.FindWhat_Edit.set_text(pattern) app.dialog.Directory_Edit.set_text(directory) app.dialog.FindAll.click()
-
Note to other readers that
pywinauto
is not included as part of the standard PythonScript plugin. To use it, you’d need to have a standalone Python installed on your system, havepywinauto
installed into that, and then tell the PythonScript plugin to prefer the standalone Python’s installed libraries.Your script utilizing
pywinauto
is very clean looking indeed, but I’m wondering about what comes after what the script does. Is it purely a visual thing, i.e., the script runs and you visually scan the Search results panel…and that’s enough for you?My reason for asking is that a logical next step is to process in some manner via Python code the results of the search. And, while your script for accessing the Find in Files interface is nice, I tried some things using
pywinauto
to obtain the search results text, and after somewhat lengthy experimentation I didn’t see how to do it. It could be just my lack of experience withpywinauto
… -
@Alan-Kilborn said in PythonScript: How to interact with dialogue boxes?:
That was my exact experience too. And even though
inspect.exe
shows the search result window,pywinauto
still can’t find it.I instead opted to use this code made by someone here. With it I could create a script that suited my own uses, which I’ve now adapted it into something more general purpose below. It searches across multiple directories, reads the search results and allows you to open the files. (To anyone that uses it: make sure ‘Purge for every search’ is enabled in the search results context menu.)
# encoding=utf-8 from ctypes.wintypes import BOOL, HWND, LPARAM import ctypes import os.path import re import time from Npp import editor from pywinauto.application import Application console.clear() console.show() console.editor.setReadOnly(False) def get_search_results(): WNDENUMPROC = ctypes.WINFUNCTYPE(BOOL, HWND,LPARAM) FindWindow = ctypes.windll.user32.FindWindowW GetWindowText = ctypes.windll.user32.GetWindowTextW GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW EnumChildWindows = ctypes.windll.user32.EnumChildWindows GetClassName = ctypes.windll.user32.GetClassNameW curr_class = ctypes.create_unicode_buffer(256) search_results = '' def foreach_window(hwnd, lParam): global search_results length = GetWindowTextLength(hwnd) if length > 0: buff = ctypes.create_unicode_buffer(length + 1) GetWindowText(hwnd, buff, length + 1) if buff.value.startswith('Search "'): search_results = str(buff.value) return False return True EnumChildWindows(FindWindow(u'Notepad++', None), WNDENUMPROC(foreach_window), 0) def open_files(): try: file_list = re.findall(r'(C:\\.*)(?: \([0-9] hits?\))', search_results) except: console.editor.addStyledText(Cell('\nNo search results detected', [1])) count = str(len(file_list)) if count == '0': console.editor.addStyledText(Cell('\nNo files in results', [1])) return prompt = notepad.messageBox('Open all ' + count + ' files?', '', 1) if prompt == 1: for file in file_list: if os.path.isfile(file): notepad.open(file) else: console.editor.addStyledText(Cell('\nFiles/directory not found', [1])) break app.wait_cpu_usage_lower(threshold=20, timeout=600) # wait until CPU usage is lower than 20% notepad.menuCommand(MENUCOMMAND.SEARCH_FINDINFILES) app = Application().connect(path=r"C:\Program Files\Notepad++\notepad++.exe") find_in_files = app.FindInFiles directories_list = 'list of directories' pattern = r'pattern' for directory in directories_list: notepad.menuCommand(MENUCOMMAND.SEARCH_FINDINFILES) app.find_in_files.FindWhat_Edit.set_text(pattern) app.find_in_files.Directory_Edit.set_text(directory) app.find_in_files.FindAll.click() app.wait_cpu_usage_lower(threshold=20, timeout=600) get_search_results() open_files() time.sleep(0.1) # this is needed if the prompt is removed from open_files()
-