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

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

Related

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

Invoke a function on tool mode script reload

How do I invoke a function every time the Script is loaded or reloaded?
tool
func _reload():
print("Changes have been made and saved! Script has been reloaded")
func _load():
print("Project was just opened! Script has been loaded")
I'm not sure what you mean by reloaded (or why it is an issue), but it probably is one of these:
When you add a Node to the scene tree (or when you enable a plugin, which is adding the EditorPlugin to scene tree of the editor), or when it is loaded (all plugins are loaded when you load the project), the code in _enter_tree will run. Similarly when it is removed (or when the plugin is disabled), the code in _exit_tree will run. Be aware that for tool scripts that you run manually (EditorScript), these don't work. So make a Node (or an EditorPlugin).
There is a signal that will notify when the script of an object changed. It is appropriately named "script_changed". So if you want to handle the situation when the tool script was modified, and thus reloaded, you could connect to that signal. You may also want to take advantage of the of _init, which is the first virtual method that Godot calls (on Nodes you can also use _enter_tree and _ready). The signal "script_changed" is emitted before _init is called in the new script.
If you want to handle when properties of a Node are modified (I'm including this since you mention "changed has been made"), you would have to use setters (with setget), or you could intercept the properties in _set.
Since you mention "Project was just opened", I think you want to make an EditorPlugin, and then you can use _enter_tree and _exit_tree.
I haven't found a way to get a notification when the currently edited scene on the editor is saved. However, saving the scene does not mean tool script are loaded or reloaded in anyway.

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.

Why can my VB6 app not open the "Open" dialog on some systems

I have a VB6 application that, despite everything manages to work on lots of systems, including the numerous Windows 7 x64 systems.
On most of them, the windows dialogs accessed through COMDLG32.OCX work just fine. However, on one particular system, this doesn't work at all. Some forms, when attempting to show the "Open" (or "Save") dialog causes an exception:
Run-time error '32765'
The common dialog function failed during initalization. This error often occurs when insufficent memory is available
Although some other forms that use it simply never show the dialog box at all. Needless to say, memory is not an issue. Microsoft have a kb article on the error where they say:
You have a Microsoft Visual Basic 6.0 program that runs on a Terminal Server, the program uses the Common Dialog control to open a file, and the following conditions are true:
The user is using a roaming profile.
There is a policy to delete the roaming profile when the user logs off.
When these conditions are true, you may receive [the error quoted above]
The conditions mentioned are not true - this is all through the (only, local) user on the system. The suggested solution involves calling the relevant API calls directly.
Reluctant to implemenet the pile of code suggested in every form relevant, I found a class already built for the purpose - CDlgEx. While this works fine on all the computers where the OCX also works fine, on the system which has problems, whenver this line is reached:
RetValue = GetOpenFileName(OFN)
where
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
and OFN is of the private type expected by the function, nothing happens. No dialog box appears, and the program simply moves on to the next line.
Further testing has shown that this only happens when running from the IDE. Running from a compliled executable, everything is fine.
Had the exact same problem. Grab the cCommonDialog class from the following link and add it to your project.
https://github.com/ziggythehamster/ignitionserver/blob/master/vbtracer/cCommonDialog.cls
You can then do something like this in your code
Private Sub Command1_Click()
Dim commonDialog As New GCommonDialog
Dim fileName As String
commonDialog.VBGetOpenFileName fileName
MsgBox fileName
End Sub

wx.TextDropTarget not working in Linux

I have a desktop application developed with wxPython. The applications runs fine under Windows and OSX (same codebase, no platform specific code). Everything works on Linux except drag and drop. I can drag just fine, but DoDragDrop always returns wx.DragCancel. I can however, drag from my application or to another app/desktop which excepts text and DoDragDrop returns wx.DragCopy.
It seems to me like the DropTargets aren't getting called. I've added debug statements to OnData, etc and they are never activated.
Has anyone seen this and know of a workaround?
Found a known issue in wxWidgets that was considered fixed, http://trac.wxwidgets.org/ticket/2763, I am able to recreate this issue on linux. I reopened the ticket.
In the meantime you can swap your StaticBoxSizers or BoxSizers. or...
This works....
parent = DropTargetCtrn.GetParent()
boxes = [x for x in parent.GetChildren() if type(x)==wx.StaticBox]
tmpParent = wx.Panel(parent)
for box in boxes:
box.Reparent(tmpParent)
box.Reparent(parent)
parent.Destroy()
This solution seems to lower the StaticBox in the window hierarchy so it don't interfere with drop events. Note, box.Lower() does not work.

Resources