AppleScript to Update iOS Apps in iTunes

Tags: , , , , ,

Bottom Line: If you don’t like having to manually update iOS apps, here’s an AppleScript to automate the process.

I’ve been thinking of trying to put together a script like this for a while. Unless I’m jailbroken, which I’m not at the moment, I really don’t ever hesitate to update my iOS apps. There are good reasons why you should not, on occasion (a buggy release that hasn’t been updated yet, a new version that loses features you need), so don’t go implementing this script without making sure you are okay with automatic app updates.

Additionally, the script is mostly using user interface (IU) scripting, which means it’s just telling OSX “where to click” and “what to type” instead of really telling it what to do programatically. This type of scripting is easy to break with updates, and doesn’t always work. For example, it’s the rough equivalent of telling your Mac “Okay, next go a little right. Now a little up. A little more right. Okay, click there!” and if any other application suddenly steals the screen’s focus, it can click in the wrong place. For these reasons, there are a lot of “delay” commands in this script (to give iTunes a chance to complete each step), and I’ve repeated a line to activate iTunes before nearly every action (to make sure it’s the frontmost app at the time of the click). As you can imagine, these UI Scripts don’t always work.

That said, it’s working for my in my testing. If you can improve on it (shouldn’t be hard), let me know.

I guess the other things to mention are:

  • After running this (and giving some time for the updated apps to download), I run a different script to automate syncing them over to my iPhone: Applescript to Sync iOS Devices in iTunes
  • Both of these are included in my “GoodMorning.app” routine that I’ve put together with Automator, which I’ll briefly post about in a few minutes
  • To run an external AppleScript in Automator, I use this (as an embedded AppleScript)

    try
    run script “/POSIX/Path/To/Script.scpt”
    end try

Enough is enough. On to the script!

  • Pingback: My GoodMorning.app Automator Routine

  • http://www.aidanfeldman.com Aidan Feldman

    Seems to be broken at the “Download All Free Updates” click part… appears to be an AXWebArea now. I know nothing about AppleScript, but if I get it working, I’ll certainly let you know!

    • http://www.n8henrie.com/ Nathan Henrie

      Hi Aidan,

      Thanks for the heads up. I just tested it, and it still seems to be working on my end (iTunes 11.0.1). Just a wild guess, but are you running it full screen? I am. I’ll have to wait until there’s another app to update to test my theory (since I just ran it successfully), but I’ve had AppleScript GUI scripting be finicky depending on full screen status. Hopefully that’s the issue, because it’s often a simple fix in the code.

      The much bigger problem with this script is that I have it set to run in the wee hours of the morning, but I have FileVault2 enabled, which locks my screen after a short period of inactivity. To my knowledge, there is no way to do GUI scripting with a locked screen. If you think of any solutions here, I’d love to hear your ideas.

    • http://www.n8henrie.com/ Nathan Henrie

      I’m not sure why it was working for me earlier, but I was able to duplicate the bug. Please see my response to Normand Despins for (what I hope is) a fix. Seems to be working again for me, at least.

  • Normand Despins

    It works until I would click on “Download All Free Updates”. I tried full screen mode or not but I get the same result: tell application “iTunes”

    activate

    end tell

    tell application “System Events”

    set frontmost of process “iTunes” to true

    exists UI element “Download All Free Updates” of UI element “iTunes store” of splitter group 1 of window 1 of process “iTunes”

    –> false

    exists UI element “OK” of window 1 of process “iTunes”

    –> false

    end tell

    • http://www.n8henrie.com/ Nathan Henrie

      Thanks for the heads up. I was able to replicate the bug and think I have it fixed (added a brief fix and comment to the code in the post).
      Looks like iTunes 11 changed the name of a UI element from “iTunes store” to “loading iTunes store.” If you replace the culprit line with tell UI element “loading iTunes store” of splitter group 1 it should work properly. Let me know if that fixes it for you.

      • mattb

        This issue persists. It works until

        tell application “System Events”

        set frontmost of process “iTunes” to true

        exists UI element “Download All Free Updates” of UI element “loading iTunes store” of splitter group 1 of window 1 of process “iTunes”

        –> false

        exists UI element “OK” of window 1 of process “iTunes”

        –> false

        end tell

        • http://www.n8henrie.com/ Nathan Henrie

          I get both false if iTunes is fullscreen, but the first returns True if windowed (and the second obviously returns false unless you’ve done the AXPress action to get the “OK” dialog response). Let me see if I can get it working with both.

          tell application “System Events”
          set frontmost of process “iTunes” to true
          exists UI element “Download All Free Updates” of UI element “loading iTunes store” of splitter group 1 of window 1 of process “iTunes”
          –> true
          exists UI element “OK” of window 1 of process “iTunes”
          –> false
          end tell

          Result:
          false

          • mattb

            Issue still persists. I am not running fullscreen mode. iTunes 11.0.1. Any other ideas? Thanks a lot!

            tell application “System Events”

            set frontmost of process “iTunes” to true

            exists UI element “Download All Free Updates” of UI element “loading iTunes store” of splitter group 1 of window 1 of process “iTunes”

            –> false

            exists UI element “OK” of window 1 of process “iTunes”

            –> false

          • http://www.n8henrie.com/ Nathan Henrie

            Huh. I’m using iTunes 11.0.2, not sure if that might be part of the problem. I can copy and paste verbatim from your comment to Applescript Editor (with addition of one “end tell” at the end) and have it return true for the first. Is iTunes at the screen that shows “download all free updates” on the upper right hand side (see screenshot)? http://cl.ly/image/1C302m202m1f

          • http://www.n8henrie.com/ Nathan Henrie

            Okay, think I got it. I think it’s a speed issue. Tried the same script on my roommate’s MBP and it was returning false (like yours), which got me thinking. His is much newer and faster than mine, so I threw in a “delay 1″ and it would return True. Comment out the delay and it’s false again. Uncomment and true again. So I brought it back to my MBP and tried the delay with fullscreen mode — and sure enough, even fullscreen mode returns true given a little time to think before the exists query.

            Give a shot to this:

            tell application “System Events”
            set frontmost of process “iTunes” to true
            delay 1
            exists UI element “Download All Free Updates” of UI element “loading iTunes store” of splitter group 1 of window 1 of process “iTunes”
            exists UI element “OK” of window 1 of process “iTunes”
            end tell

            If that returns true for the first exists statement, then this is likely the problem. I’ve updated the script in the post to fix this issue by adding several delays.

          • mattb

            Hi. It wasn’t a delay issue, it was the sidebar in iTunes that was preventing it from working. Once I hid the sidebar (opt-cmd-s), the script runs normally and successfully. Thank you for all your help! This is an excellent tool and I will use it often. At least now you know that it wont run unless you hide the sidebar! :)

          • http://www.n8henrie.com/ Nathan Henrie

            Gah, I should have known! I forgot that I had hidden the sidebar on my roommate’s computer in the process of testing. Interestingly the delays also seemed to matter, but again I think this may be because Applescript is relatively slow. Anyway, thanks a ton.

            I’ve updated the script in the post with hopefully everything we’ve discussed up to this point, including iTunes 10/11 compatibility (untested, commenters let me know if you have access to iTunes 10), sidebar compatibility, and “delay 1″s for potential fullscreen issues. Phew!

  • Normand Despins

    When I run my Mac in english, it runs smoothly. Thank-you so much!!! As my first language is Canadadian-french, I’ll have to translate “loading iTunes store” and “Download All Free Updates”. No problem translating “Download All Free Updates” as I can see the french translation in iTunes UI but how to know the exact translation of “loading ITunes store”?

    • http://www.n8henrie.com/ Nathan Henrie

      I’d suggest one of two options.

      1. Use Accessibility Inspector (http://goo.gl/y6492), use cmd F7 to “lock” it while you hover the mouse over the “Download All Free Updates” button and navigate to AXApplication -> AXWindow:AXStandardWindow -> AXSplitGroup -> (possibly another split group depending on sidebar status -> ) AXWebArea then under AXChildren click 2 (which is an AXLink). Under AXTitle you should see the text for “Download All Free Updates” (I realize you can just look at the button for this one, as you’ve said). Then do the same for “loading iTunes store” by double clicking “AXWebArea” up to and looking at the AXDescription. Here is what I see for the first: http://cl.ly/image/1b2B2M2y1F2Z and this for the second: http://cl.ly/image/0G0Y2M191h2t

      2. This may be the easier option. First, get iTunes to the screen in question (the one with the “Download All Free Updates” button). Then open up Applescript Editor and use System Events’ “UI Elements” query and check the “Result” pane to get all valid UI elements. Pick the appropriate one, then add a “tell / end tell” statement for that UI element, and run the UI elements query within that element. Kind of hard to explain, but it makes sense once you try it. Here is a screenshot (http://cl.ly/image/021b2x2w3G42) and a here is a basic framework you can paste into Applescript Editor to get started: https://gist.github.com/n8henrie/5198984

      • Normand Despins

        Wow, Thank-you so much Nathan !!! It works GREAT in french. Your explanation was very easy to follow and within a few minutes, I was up & running. I used the #1 example but after making it worked, and for my own knowledge, I tried the #2 example. I’m stuck on ” use System Events’ “UI Elements” query and check the “Result” pane to get all valid UI elements”. I must admit I didn’t succeed with explanation #2. I don’t want to ask you more efforts as everything goes well on my side but I would appreciate more detailed explanations on item #2 if ever you have spare time… :-))) It’s only to get some experience on AppleScript. As soon you come in Canada, I will pay you a BIG beer !!! Thanks again !

        • http://www.n8henrie.com/ Nathan Henrie

          Ha! Well it certainly makes me happy to have helped. I was considering a new post about the strategy I was trying to describe in #2, so I went ahead and wrote it: http://n8henrie.com/2013/03/a-strategy-for-ui-scripting-in-applescript/ . Hopefully that helps explain things a little better (although maybe not, I’m pretty tired at the moment so my writing is probably not at its best!).

          • Normand Despins

            Thank-you so much Nathan ! Tutorial very well done. A very good training is there for the very next days.

  • Pingback: A Strategy for UI Scripting in AppleScript