A visible window cannot be recognized in pywinauto - python-3.x

While writing scripts, I am attempting to look at some items in the Device Manager. The only issue is that pywinauto cannot see the device manager. Below is what I get when looking for "Device Manager":
Could not find 'Device Manager' in 'dict_keys(['', 'Pane', 'Taskbar', 'Pane0', 'Pane1', 'Pane2', 'TaskbarPane',
'Pane3', 'NetBannerPane', 'Pane4', 'NetBanner', 'ListBox', 'Program ManagerPane', 'Program Manager', 'Pane5'])'
I have attempted to print_control_identifiers() for all of the items listed here however, none of them are the device manager. Looking within Inspect.exe, I can clearly see that there is a window with the title of "Device Manager".
I've even tried to access it via:
dlg=Desktop(background='uia')
dlg.window(class_name="MMCMainFrame").print_control_identifiers()
However, it also provides an error stating that it's an invalid name for the element and it cannot be found. Has anyone else ever attempted to use pywinauto to look at the Device Manager? Or had an issue being unable to find an element

try using this code:
dlg = Desktop(background="uia")
dlg.window(title="Device Manager").print_control_identifiers()
Use title or title_re instead of class_name. dlg.window(title="Device Manger") returns device manager window handler if window is opened already.
Heres find window documentation

Related

Running 'System Events' from Excel For Mac Via VBA Results in Invalid Procedure 5 Error

I am trying to run a very simple apple script from VBA. The VBA code is:
NavigationJunk = AppleScriptTask("Budget Report Apple Scripts/NavigationMoveWindowsAppleScript.scpt", "NavigationMoveWindowLeftHandler", "")
The script reads:
on NavigationMoveWindowLeftHandler(Junk)
tell application "System Events" to key code 123 using {option down, control down}
end NavigationMoveWindowLeftHandler
where the complete path for the .scpt is: "/Users/Andrew/Library/Application Scripts/com.microsoft.Excel/Budget Report Apple Scripts/NavigationMoveWindowsAppleScript.scpt" (this is the correct path as documented here: Apple Script Task Throwing an Error 5
This code simply performs the key stroke cntrl+option+left arrow. That key stroke is a shortcut for the app Magnet to move the window to be half screen left.
This worked prior to updating my system to MacOS Ventura. I attempted to restart, uninstall Excel, reset the permissions in System Settings/Privacy/Automation (as documented here: Reset MacOS Privacy Settings) and reinstall Excel. When I tried to run the VBA code I was prompted to grant permission to system events and still received an invalid procedure error. I verified that when I call the handler from within the Apple Script Editor the system performs the keystrokes with no issues. I assume this is some sort of permission thing...How do I fix this?
Of note: this code called prior to the AppleScriptTask above runs just fine:
AppleScriptResult = Split(AppleScriptTask("Budget Report Apple Scripts/NavigationMoveWindowsAppleScript.scpt", "NavigationGetScreenResolution", ""), " ")
This is curious because the .scpt is the same file and calls a different handler:
on NavigationGetScreenResolution(Junk)
return do shell script "system_profiler SPDisplaysDataType | grep Resolution"
end NavigationGetScreenResolution
and runs just fine. Any help here would be greatly appreciated

pywinuto - click_input() function clicks on random node of tree view

I'm trying to automate the mmc (snap in console) type desktop app. Where I need to expand the tree.
Try 1 -
But when I do use expand() function it generates error popup which says that "the child nodes does not exists". After this script simply stops with no error message on console unless ok button is clicked on error popup. This I suspect because when tree node expanded it triggers some event which brings child nodes under it and somehow pywinauto is not getting Childs of this node. Please note that this error popup does not come up when the step is done manually.
Try 2 -
When I tried with select() then too same behavior observed as above. It generated same error popup.
Try 3 -
I tried click() and click_input() functions and it clicks on random tree node but not on the tree node on which it is called.
The all above trials are of my application which is not public.
For reproducing this issue I have tried it on common application available on windows OS. And we can see that the 3rd is still reproducible.
Reference code -
import time
from pywinauto.application import Application
from pywinauto import Desktop
app = Application().start(r'cmd.exe /c "C:\Windows\system32\perfmon.msc"', wait_for_idle=False)
app = Application(backend="win32").connect(title='Performance Monitor', timeout=10)
main_wind = app.window(best_match='MMCMainFrame', top_level_only=False)
console_wind = main_wind.child_window(best_match="MDIClients").child_window(best_match='MMCChildFrm').child_window(class_name="MMCViewWindow")
tree = console_wind.TreeView # print_control_identifiers()
children = tree.get_item(["Performance","Data Collector Sets"]).expand().get_child("System").expand().get_child('System Diagnostics')
print(children.text())
# below line will select the System Diagnostics
children.select()
time.sleep(4)
# Below line should click on System Diagnostics but it does NOT and same happens for click() function
children.click_input()
Any help will be really helpful in knowing why this click() and click_input() clicks on random tree node and Why expand() and select() method generates the non functional error popup?
Please mention if there is concrete workaround to this.
versions -
Windows OS 10, build 20H2
Python 3.10.4
comtypes 1.1.11
pip 22.0.4
pywin32 303
pywinauto 0.6.8
setuptools 61.2.0
six 1.16.0
wheel 0.37.1
TIA..
I have referenced some stack overflow and github issue tracker as for this problem as below but nothing works.
Treeview problem
select() for TreeView items (and similar) leads error if this selection calls other dialogs etc
Python: Click by coordinate inside a window
This was all because of incorrect backend API used for snap in control application. Unfortunately my POC I did on win32 API where it worked because I was doing some initial steps manually hence the problem I was facing(explained in try1) was not there and everything was working perfectly fine.
As soon as I switched the backend to UIA it gave me different identifiers for the controls that I used previously. Now I used this identifiers and started using UIA documentation and everything started working smoothly.
Also in my investigation there is no proper way to identify the backend API for the desktop application unless you try both and figure out which works for you.
Suggestion to readers - If you are using win32 API as backend there are different api methods available for that in the documentation. and for UIA backend different. read documentation carefully.
You can try the uispy tool and find that perfmon.msc can be automated with uia

python pywinauto file selection dialog

I am in the process of automating a firmware update for a specific component we use a work a lot. I have the automation of the gui completed (and working) except for this particular screen.
What I need to do, is have the program automatically navigate to the correct folder (standardized across machines) and select the correct file to use for the update.
Here is my code so far:
from pywinauto.application import Application
app = Application(backend='win32').connect(title_re=".*EBDS*", found_index=0)
main_dlg = app.window(title_re=".*EBDS*", found_index=0)
main_dlg.child_window(title="Launch Control Panel", control_type="System.Windows.Forms.Button").click()
sub_dlg = app.window(title_re=".*Bill Acceptor*", found_index=0)
sub_dlg.child_window(title="Open", control_type="System.Windows.Forms.Button").click()
sub_dlg.child_window(title="Download", control_type="System.Windows.Forms.Button").click()
file_dlg = app.window(title_re=".*download*", found_index=0)
It has a couple sub windows that pop up after clicking, thus the main_dlg, sub_dlg, and file_dlg.
I have already told it to select the download button, and it pops up the "select a file to download" window.
What I need to do now is be able to specify the path (where it says This PC), change the file type (currently says Bin files), and select the correct file.
I have done a "print control identifiers" and here is the link to the txt file of that output (it's over 3k lines, so I didn't want to paste it here) Control Identifiers .txt
What I then did was I correctly (manually) went through the steps to get it where it needs to be, and did another "print control identifiers." Again, this is over 3k lines long, so here is a Link to that output.
Assuming that I'm doing this right, the file path location in the gui is:
file_dlg.child_window(title="Select a file to download.", class_name='#32770').child_window(class_name="WorkerW").child_window(class_name="ReBarWindow32").child_window(class_name="Address Band Root").child_window(class_name="msctls_progress32").child_window(class_name="Breadcrumb Parent").child_window(title=".*Address:*", class_name="ToolbarWindow32")
The question is, how do I interact with that object specifically? A .click() or .sendkeys() both error out.
Bonus points if you can figure out how to change the file type.
I'm open to an easier/different way of doing this, however this has to be deployable to a couple hundred machines that don't have the same screen size, ergo I cannot use pyautogui and pixel counts.
Any ideas?
You can enter the full file path to the edit box and click "Open" button. It should look like this:
file_dlg = app.window(title_re=".*Select a file to download*", found_index=0)
file_dlg.FileNameEdit.set_edit_text("full_path_to_file")
file_dlg.child_window(title="&Open", control_type="Button").click()
I assume you have to bypass .click_input() and .type_keys(...) usage as they require active desktop which is hard to maintain on a big pool of machines.

MAC OS X difference between "open APP.app" and "APP.app/content/MacOs/APP" shell scripts

Somehow I get a problem, if I call an application twice or several times but only one instance should be running (which is desired).
First some (probably necessary) background information:
working on MAC OS X El Capitan (10.11.6)
I've got an Application made by node.js, electron and build by "npm build -m" (let's call it APP.app)
I installed the application App.app into program-folder by opening the built dmg-file and move it into the program-folder
Then I start the application App.app by click on the App.app-icon in program-folder
The application starts with a visible Window and also has an hidden background process running
If I close the visible Window, the App.app-Icon remains in the dock (which is okay, since the background-process is still running)
Now (and this is the difference to the windows build and running in windows), if I click again on the App.app-Icon in the program-folder, I only get a focus on the already running application INSTEAD of opening the window and close the old application (I can see te focus switch/activation by the switching menu name beside the apple-logo on top of the screen; it becomes "App")
the closing of the previous running instance is defined in electron code in the init-method as follows:
var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) {
console.info('starting new instance');
initInternal(commandLine);
// Someone tried to run a second instance, we should focus our window.
var windows = options.closeWindowsOnRestart ? Browser.getAllWindows() : appWindows.slice();
windows.forEach(function (val, index) {
val.close();
});
readyCallback();
});
So, I did some homework and could figure out following:
my App.app-icon-click should look something like open /Applications/App.app
with this, I get the same problem as descriped above if I call it again (it only focusses the already opened window)
Now comes the funny part. If I open the application by calling directly /Applications/App.app/content/MacOS/App.app the old application-instance is closed and new App.app-application is started
I read through open-manual and could figure out, that if I use the -n-flag, the application starts succesful a new instance, too. (open /Applications/App.app -n)
I was wondering WHY? Do you have any clues? What is the difference between open and directly call of the application?
I suggest that the info.pklist in App.app-package is making the open-call different to the direct call of App.app.
BTW:
Unfortunately I already tried to add try-catch-blocks to debug the problem, but open does not give an output to terminal, it just opens the call whereas the direct call does not throw an error and everything works fine.
Anyway, I believe it's more a MAC OS X problem than an App.app-problem.
Hopefully there's somebody with same problems and a solution for me
Don't hesitate to ask for more details, if needed.
Short Version:
open starts the application with the LaunchService (and possible
added launch-parameters in info.plist)
whereas direct call of the
application just starts the application iself without any other
launch-options
*Long Version *
I read through the open manual (man open; Source: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/open.1.html) and could figure out, that "the default application as determined via LaunchServices is used to open the specified files" if you click on an item.
So I read through the LaunchService-documentation and could figure out following:
"Opening Items by File-System Reference [...] default way:
If the designated item is an application: [...]
If the application is already running, it is activated (brought to the front of the screen) and sent an 'rapp' (“reopen
application”) Apple event."
(Source: https://developer.apple.com/library/content/documentation/Carbon/Conceptual/LaunchServicesConcepts/LSCTasks/LSCTasks.html#//apple_ref/doc/uid/TP30000999-CH203-TP9)
This reflects exactly my watching that if I click on the icon the second time, the app is just focussed/activated.
Thus I need the possibility to tell the application to open a new instance (oapp-event) instead of activating the already opened application (rapp-event)
Further reading lead me to following informations:
"Launch Options When opening an application (whether by itself or to
open one or more documents or URLs), you can specify various launch
options to control the manner in which it is launched or activated.
These can include: [...] Whether to launch a new instance of the
application, even if another instance is already running"
(Source: https://developer.apple.com/library/content/documentation/Carbon/Conceptual/LaunchServicesConcepts/LSCConcepts/LSCConcepts.html#//apple_ref/doc/uid/TP30000999-CH202-BABBJHID)
Thus I only need to add the "launch option" to define, that a new instance should be created instead of activating the existing one. But there's not written what the launch-option for it is and how they will be applied to the application (I suggest it belongs into info.plist-file).
So at least this is the answer to my original question, so I posted it here.
open - starts the application with the Launch-Service (and the defined option-parameters in info.plist)
whereas direct call of the application just starts the application iself without any other launch-options

I would like to get process name,process id ,Process Path,Product Name Window Title

how to get process information like this format
my develop tools is visual c++ 2008
I would like to get process name,process id ,Process Path,Product Name Window Title
but i don't know how to connect those information toghter
I am assuming you want this information about youself (the running process).
To get the process name and path use the GetModuleFileName function to get the full path and use the last element in the path as the process name.
To get the process id use the GetCurrentProcessId function.
To get the window title use the GetWindowText function.

Resources