No internet connection
  1. Home
  2. How to

Open / Close windows of programs running in the background with menu bar icons via stream deck button

By Micah Loken @Micah_Loken
    2022-03-01 22:53:24.498Z

    Title

    Open / Close windows of programs running in the background with menu bar icons via stream deck button

    What do you expect to happen when you run the script/macro?

    There is a program called "Resilio Sync" that runs in the background and has an icon present on the top right menu bar that indicates it is open.

    I am hoping that a button on the stream deck will be able to launch the application (if it is NOT running in the background), or open the application's main window if it is running in the background, or close the application's main window (but remain open in the background).

    The problem is, I am unable to figure out just how to do this using if/else statements. I think I might be close but need some help.

    Thanks!

    Are you seeing an error?

    I think the script is running multiple times and getting confused because I can't figure out the best way to code what I am hoping for. Haha!

    What happens when you run this script?

    When I click the stream deck button, the program will launch (if it is not launched) and will throw "TEST 1" up. This is great!

    When the program is open in the background, and I click the stream deck button, the program will open as expected and will throw up "TEST 3"

    When the program is open and the main window is at the front, the script will close the main window, then "TEST 2" will appear but then a bunch of looped error messages come up for both "TEST 1" and "TEST 3" multiple times over and over until the script stops because it's being overloaded.

    Clearly this is something I am doing and would love some help with this one! Thanks again!

    How were you running this script?

    I used a Stream Deck button

    How important is this issue to you?

    3

    Details

    {
        "inputExpected": "There is a program called \"Resilio Sync\" that runs in the background and has an icon present on the top right menu bar that indicates it is open.\n\nI am hoping that a button on the stream deck will be able to launch the application (if it is NOT running in the background), or open the application's main window if it is running in the background, or close the application's main window (but remain open in the background).\n\nThe problem is, I am unable to figure out just how to do this using if/else statements. I think I might be close but need some help.\n\nThanks!",
        "inputIsError": true,
        "inputError": "I think the script is running multiple times and getting confused because I can't figure out the best way to code what I am hoping for. Haha!",
        "inputWhatHappens": "When I click the stream deck button, the program will launch (if it is not launched) and will throw \"TEST 1\" up. This is great!\n\nWhen the program is open in the background, and I click the stream deck button, the program will open as expected and will throw up \"TEST 3\"\n\nWhen the program is open and the main window is at the front, the script will close the main window, then \"TEST 2\" will appear but then a bunch of looped error messages come up for both \"TEST 1\" and \"TEST 3\" multiple times over and over until the script stops because it's being overloaded.\n\nClearly this is something I am doing and would love some help with this one! Thanks again!",
        "inputHowRun": {
            "key": "-MpfwmPg-2Sb-HxHQAff",
            "title": "I used a Stream Deck button"
        },
        "inputImportance": 3,
        "inputTitle": "Open / Close windows of programs running in the background with menu bar icons via stream deck button"
    }

    Source

    
    const application = sf.ui.app("com.resilio.Sync");
    
    if (!sf.ui.app("com.resilio.Sync").exists) {
        sf.app.launch({ path: "/Applications/Resilio Sync.app" })
        throw "TEST 1";
    } else if (sf.ui.frontmostApp.activeBundleID === "com.resilio.Sync") {
        application.getMenuItem("Window", "Close").elementClick();
        throw "TEST 2"
    } else (sf.ui.frontmostApp.activeBundleID !== "com.resilio.Sync") {
        sf.ui.app("com.resilio.Sync").getElement("AXExtrasMenuBar").popupMenuSelect({
            menuPath: ["Open Resilio Sync"],
        });
        throw "TEST 3";
    }
    
    

    Links

    User UID: xccrytGOrsRRPYHLwbzTvsapDt53

    Feedback Key: sffeedback:xccrytGOrsRRPYHLwbzTvsapDt53:-Mx6g2814nvtyTIDDH38

    Feedback ZIP

    Solved in post #10, click to view
    • 10 replies
    1. Hm that's very interesting. Do you by chance have any triggers assigned to the script?

      1. MMicah Loken @Micah_Loken
          2022-03-02 00:25:29.604Z

          There is no trigger. It's just this script straight up assigned to a deck key.

          This application is a bit different because it does not have a place in the dock nor can it be switched to via the application switcher (⌘+Tab) because it is an app that runs in the background.... unless the application window is left open behind other apps. I really don't need the application window open all of the time. I just toggle back and forth from it from time to time to check on it and would like that function to be automated via a button press on the stream deck. Hope that helps with more context.

          1. Hm.. Then I don't have an immediate idea on why that would happen :/

            1. MMicah Loken @Micah_Loken
                2022-03-02 17:42:50.213Z

                Christian, is there a way to place a 'stop' command (kind of like 'break;' under the 'if' 'else if' and/or 'else' statements after 'throw'... or is 'throw' supposed to stop the script?

                Another thought... perhaps the problem it's the way I have structured the hierarchy if the 'else' statements?

                1. throw stops the script.

                  The weird thing here is why the subsequent calls of the script happens.

                  1. What you want to be looking for in the log file is stuff like this:

                    
                    01.03.2022 14:08:18.83 <info> [Backend]: #StreamDeck: KeyDown (7,1) -> Open/Close Resilio Sync
                    
                    01.03.2022 14:08:18.83 <info> [Backend]: >> Command: Open/Close Resilio Sync [user:default:cl08j644z0001ft1057wxe2ww]
                    
                    01.03.2022 14:08:18.91 <info> [Backend]: << Command: Open/Close Resilio Sync [user:default:cl08j644z0001ft1057wxe2ww]
                    

                    The #StreamDeck is the trigger being registered. The >> Command indicates the command starts running and the << Command indicates the command stopped running. If you see `!! Command" the command stopped due to an error or a throw statement.

                    1. MMicah Loken @Micah_Loken
                        2022-03-02 19:04:34.063Z

                        Thanks for this. Makes sense!

                        It must be something with my code, if you copy my code I pasted above and put it in a script... you'll notice you are unable to add code below it (it greys out). It's almost surely something in the language I am doing incorrectly and I just can't see it.

                        Hmmm....

                        1. Ah yea:

                          } else (sf.ui.frontmostApp.activeBundleID !== "com.resilio.Sync") {
                          

                          should have been

                          } else if (sf.ui.frontmostApp.activeBundleID !== "com.resilio.Sync") {
                          
                        2. In reply tochrscheuer:
                          MMicah Loken @Micah_Loken
                            2022-03-02 19:28:59.595Z

                            Weirdly... now I am receiving this message when attempting to run the 'Open/Close Resilio Sync' script via deck button press. Tried a restart app / restart computer to no avail too...

                            02.03.2022 11:25:44.44 <info> [Backend]: Error parsing command Open/Close Resilio Sync (Line 10): Unexpected token {
                            StreamDeck: Command user:default:cl08j644z0001ft1057wxe2ww not found
                            

                            I guess it's safe to say this whole script is causing more grief than the simple task I am attempting :)

                            1. In reply tochrscheuer:
                              MMicah Loken @Micah_Loken
                                2022-03-03 07:41:47.890Z

                                I think I figured it out. It seems to be working and stable.

                                
                                //Defining the application we are working with
                                const applicationResilio = sf.ui.app("com.resilio.Sync");
                                
                                //If the application IS NOT open, then open it
                                if (!applicationResilio.exists) {
                                    sf.app.launch({ path: "/Applications/Resilio Sync.app" });
                                    throw "APP LAUNCH SUCCESS"
                                
                                //If the application's main window is open somewhere AND is NOT the focussed application, then bring that window to the front
                                } else if (applicationResilio.mainWindow.exists && sf.ui.frontmostApp.activeBundleID !== "com.resilio.Sync") {
                                    applicationResilio.appEnsureIsRunningAndActive();
                                    throw "APP WINDOW BROUGHT TO FRONT"
                                
                                //If the application's main window is open AND it IS the focussed application, then close the window
                                } else if (applicationResilio.mainWindow.exists && sf.ui.frontmostApp.activeBundleID === "com.resilio.Sync") {
                                    applicationResilio.getMenuItem("Window", "Close").elementClick();
                                    throw "APP WINDOW CLOSED"
                                
                                //If the application IS open AND the application's main window is NOT open, then open the application's main window from the Menu Bar
                                } else if (applicationResilio.exists && sf.ui.frontmostApp.activeBundleID !== "com.resilio.Sync") {
                                    applicationResilio.getElement("AXExtrasMenuBar").popupMenuSelect({
                                        menuPath: ["Open Resilio Sync"],
                                    });
                                    throw "APP WINDOW OPENED"
                                }
                                
                                

                                It is interesting dealing with an application whose main window closes when you "Quit" or "Command + Q" and the program itself stays open in the background. Ironically, your application (SF) does the same thing. :)

                                Reply1 LikeSolution