26 Replies Latest reply: Nov 15, 2014 8:22 PM by areohbee RSS

    Lion & osascript

    areohbee Community Member

      I have several plugins that use on-the-fly generation of text scripts expected to be executed by osascript interpreter.

       

      That worked fine up through Snow Leopard, but Lion usually disallows such stuff.

       

      Any ideas for work-around?

       

      Rob

        • 1. Re: Lion & osascript
          Matt Dawson Community Member

          Nothing specific, sorry. Is there a way that you could write a static script that gets authorised somehow, and have it read configuration from a file instead? Or maybe its the location being written to (/tmp ?) that doesn't support execution of scripts?

           

          But when testing ideas for a work around I'd suggest making sure it can work in a sandboxed environment. Now that there is a Mac App Store version of Lightroom I suspect it will only be a matter of time before Apple force them to have it run in sandboxed mode.

           

          Matt

          • 2. Re: Lion & osascript
            areohbee Community Member

            Example script (for saving metadata):

             

            "osascript" -e 'tell application "Lightroom" to activate' -e 'tell application "System Events"' -e 'key down command' -e 'keystroke "s"' -e 'key up command' -e 'end tell'

             

            and the error code: 256 (returned by osascript interpreter).

             

            I have assumed the problem was related to security, but I suppose it could be syntax or some other incompatibility (reminder: exact same script has been working for years previously...)

             

            It could very well be that compiling the script(s) into app(s) would solve the problem. e.g. no problems executing exiftool from plugins.

             

            Since scripts are not being written to disk I don't see how disk permissions (e.g. /tmp) would be a factor, unless such writing is implicit...

             

            How does one "make sure it works in a sandboxed environment"?

             

            Rob

            • 3. Re: Lion & osascript
              Matt Dawson Community Member

              Rob Cole wrote:

               

              How does one "make sure it works in a sandboxed environment"?

               

              I'd suggest reading up about Mac's sandbox and temporary exception entitlements.

               

              I haven't seen anyone say that the Mac App Store version of Lightroom will become sandboxed but I can't see how they will be able to avoid it. If you are going to be reworking this part of your code anyway it wouldn't hurt to think ahead.

               

              Matt

              • 4. Re: Lion & osascript
                areohbee Community Member

                Thanks Matt.

                R

                • 5. Re: Lion & osascript
                  jarnoh Community Member

                  So, the Mac App Store version can't launch any external scripts?  Can anyone confirm that?  Can I somehow emulate the App Store version's sandboxing features with sandbox-exec?

                   

                  I have a plugin that does keyboard stuffing (http://www.capturemonkey.com/excessor), it's working fine on Lion and Mountain Lion, but I only have regular downloadable version of Lightroom.  I'm not too eager to purchase another copy just for testing...

                  • 6. Re: Lion & osascript
                    areohbee Community Member

                    Hi Jarnoh,

                     

                    Is your excessor plugin feeding text scripts to osascript to execute?

                     

                    I've been trying to figure out whether it's all Lion systems or just some that have the problem. It's starting to sound like it's just some - maybe just the App Store versions. Hmm....

                     

                    Rob

                    • 7. Re: Lion & osascript
                      jarnoh Community Member

                      Yes, Excessor uses osascript to stuff in keyboard events.

                       

                      If it helps, I can try out your plugin, just tell me what to install and how it is supposed to work

                      • 8. Re: Lion & osascript
                        Matt Dawson Community Member

                        To be clear, I am certain that the Lightroom 4.1 MAS version is not

                        sandboxed. So the problems you are experiencing are likely to do with the

                        operating system upgrade only.

                         

                        I was advising Rob that if he changes code he should future proof it to

                        work in a sandboxed environment. I suspect that a future version will be

                        forced by Apple to introduce sandboxing so might as well get ahead of the

                        curve while making any change.

                         

                        I am not aware of any way to simulate a sandboxed MAS version without

                        having purchased the MAS version first. Sorry.

                         

                        Matt

                        • 9. Re: Lion & osascript
                          areohbee Community Member

                          Thanks Matt,

                           

                          So next question is:

                           

                          Why does it work on some (Lion) systems, but not others?

                           

                          And of course:

                           

                          * Is it possible for the user to change system config so that it works, and for the sake of completeness:

                          * Is it possible for the plugin programmer to change code so that it always works...

                           

                          Rob

                          • 10. Re: Lion & osascript
                            Matt Dawson Community Member

                            I don't have much experience with Mac, and none with Lion, so can't give

                            you any definitive answers.

                             

                            It is possible Lion has introduced some additional security around the

                            functionality you are relying upon and that is causing the issues you are

                            seeing. It might be the MAS version that is hitting the issue but is a Lion

                            triggered issue and not an LR sandboxing one. Pretty sure I read somewhere

                            there were malware related features in Lion. I wouldn't be surprised if key

                            press stuffing and dynamic scripts were viewed with suspicion by such a

                            feature.

                             

                            Matt

                            • 11. Re: Lion & osascript
                              jarnoh Community Member

                              Rob, are you seeing this behaviour yourself, or has one of your users reported it?  Are you getting multiple reports or just single incident?

                               

                              I haven't heard of any problems with Lion keyboard shortcuts with my plugins, but there isn't that many users with OS X 10.7.

                               

                              I find it hard to believe that there would be issues with dynamic scripts, maybe there's a hidden switch to adjust System Events permissions somewhere (and someone has non-default configuration...)

                               

                              BTW. My plugin skips the Lightroom activate part, since its invoked from menu, I'm expecting Lightroom to be already active

                               

                              Jarno

                              • 12. Re: Lion & osascript
                                areohbee Community Member

                                Hi Jarno,

                                 

                                I have not seen it myself, but a couple of clients have reported it.

                                 

                                You could be on to something - might have nothing to do with text osascript execution, and be more about the "activate" part.

                                 

                                I'll consider making a change for testing.

                                 

                                If you would try for me on your Lion system, ChangeManager. On File Menu / Plugin Extras, choose Lock. That will attempt to save metadata using "Cmd-S".

                                 

                                If it's not obvious from the log file what happened, enable "Verbose Logging" in top section of plugin manager.

                                 

                                Thanks bunches,

                                Rob

                                • 13. Re: Lion & osascript
                                  jarnoh Community Member

                                  Here's the logfile

                                   

                                  2012-07-30 20:09:26 +0000, INFOLocking one photo
                                  2012-07-30 20:09:26 +0000, INFO1 photo photos under consideration for snapshot and/or mark...
                                  2012-07-30 20:09:26 +0000, DEBUGMain style: RC Finished, Summarized
                                  2012-07-30 20:09:26 +0000, DEBUGSnapshotted /Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.ORF with Master 2012-07-30 23:09:26 Locked (test)
                                  2012-07-30 20:09:26 +0000, DEBUGLens profile corrections are defined, but disabled.
                                  2012-07-30 20:09:26 +0000, DEBUGMarked edit history of /Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.ORF with details: no adjustments
                                  2012-07-30 20:09:26 +0000, DEBUGMarked edit history of /Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.ORF with profile: Adobe Standard
                                  2012-07-30 20:09:26 +0000, DEBUGMarked edit history of /Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.ORF with snap: Master 2012-07-30 23:09:26 Locked (test)
                                  2012-07-30 20:09:26 +0000, DEBUGsnapshotted and/or marked /Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.ORF
                                  2012-07-30 20:09:26 +0000, ERROR****** ERROR #2: Unable to lock /Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.ORF because Non-zero exit code returned by command: "chmod" a+w "/Volumes/dada/Pictures/2012/2012-07/2012-07-15/_7150537.xmp", exit-code: 256
                                  2012-07-30 20:09:26 +0000, INFOFinalizing to lockage of 0 photos...
                                  2012-07-30 20:09:26 +0000, DEBUGPrevious lib filter table restored.
                                  2012-07-30 20:09:26 +0000, DEBUGPrevious lib filter table restored.
                                  2012-07-30 20:09:26 +0000, DEBUGBackground state changed to: running
                                  2012-07-30 20:09:26 +0000, INFO0 photos locked.

                                   

                                   

                                   

                                  I'm not seeing any mention of osascript, and the chmod probably fails because the XMP is not generated. 

                                   

                                  From commandline, osascript code mentioned before works fine (I'm seeing the warning dialog, because I clicked reset-all-warnings buttons just to be sure)

                                   

                                  I'm guessing its problem with your code, but i didn't understand the stuff enough to add more logging :-)

                                  • 14. Re: Lion & osascript
                                    jarnoh Community Member

                                    I rerun it, but first saved XMP file myself (Cmd+S).  Now it works   So the problem is not the osascript, but chmod

                                    • 15. Re: Lion & osascript
                                      areohbee Community Member

                                      Well that's a new one on me - thanks for turning that up .

                                       

                                      Still, on some systems, the osascript is clearly a problem (error message in log file is specific and unambiguous...).

                                      • 16. Re: Lion & osascript
                                        jarnoh Community Member

                                        Still, I'm not buying this as a wide spread problem.  It's definately not a SDK problem anyway.

                                         

                                        Perhaps the users system is just misconfigured, or could use the magic of Disk Utility's repair permissions.  Error code 256 indicates a file access error, perhaps they have wrong permissions under /System/Library/CoreServices/System Events.app or something...

                                        • 17. Re: Lion & osascript
                                          areohbee Community Member

                                          jarnoh wrote:

                                           

                                          I'm not buying this as a wide spread problem.

                                          Problem "solved":

                                          1. access for assistive devices needs to be enabled:

                                          mac_enable_for_osascript.jpg

                                          2. even if it's enabled, there's a bug in the OS (or at least there used to be) whereby even if enabled, user may need to disable, then reenable.

                                           

                                          After doing so, feeding text scripts to osascript interpreter may just work.

                                           

                                          Rob

                                          • 18. Re: Lion & osascript
                                            jarnoh Community Member

                                            Yes, assistive devices option might be required for some operations, but I think I'm actually not using it in Excessor.

                                             

                                            Additionally, you can also enable it from osascript, this will trigger a password dialog if it is not already set:

                                             

                                            osascript -e 'tell application "System Events" to set UI elements enabled to true'

                                             

                                            As a side note, I think the UI dialog option will be moved to different place in OS X 10.9.

                                            • 19. Re: Lion & osascript
                                              areohbee Community Member

                                              jarnoh wrote:

                                               

                                              assistive devices option might be required for some operations

                                              This operation fails without the assistive devices enabled:

                                               

                                              "osascript" -e 'tell application "Lightroom" to activate' -e 'tell application "System Events"' -e 'key down command' -e 'keystroke "'"' -e 'key up command' -e 'end tell'

                                               

                                              Note, in this example, the keystroke character is an apostrophe - used for creating virtual copies, in Lr4-. But also applies when keystroke is the "s" character for saving metadata...

                                               

                                              In other words, assistive devices is required for keyboard stuffing, via such scripts, or so it seems to me at this point.

                                               

                                               

                                              jarnoh wrote:

                                               

                                              osascript -e 'tell application "System Events" to set UI elements enabled to true'

                                              This is might be a good measure to take if script fails - thanks for the tip.

                                               

                                               

                                              Rob


                                              • 20. Re: Lion & osascript
                                                jarnoh Community Member

                                                Keyboard events work for me even without this option set on, but e.g. reading window controls fails with error message.  I don't know if that is the case always, but I've had less need for user support on Mac than on Windows (I used JScript for event stuffing and it's a mess with 64bit Windows because many installers corrupt its registration).

                                                • 21. Re: Lion & osascript
                                                  areohbee Community Member

                                                  jarnoh wrote:

                                                   

                                                  Keyboard events work for me even without this option set

                                                  Hmm - would you mind posting an example script - since behavior seems different, I can't help but wonder if there is some distinguishing difference in the scripts we're using. - thanks.

                                                   

                                                  PS - In Windows, just use auto-hotkey - so far: problem free (well, other than it won't work if a dialog box is open..., which is a problem regardless of which method you use, right? - unless you can figure out how to target around the dialogs...).

                                                   

                                                  e.g. compile this into an AHK exe and pass keystroke string on command line:

                                                   

                                                   

                                                  /*

                                                      SendKeysAHK.ahk

                                                  */

                                                   

                                                   

                                                  /*

                                                      Get unique window identifier of Lightroom's main app window.

                                                   

                                                      Initial motivation: Make sure Lightroom will be the recipient of emitted keystrokes.

                                                   

                                                      So far, for titles, we have:

                                                          {Catalog} - Adobe Photoshop Lightroom - {Module}

                                                          Lightroom

                                                          Lightroom (x%)

                                                   

                                                      ###1 Not sure how to handle case if a dialog box is open, plugin or otherwise.

                                                   

                                                      ahk_class is AgWinMainFrame

                                                  */

                                                  GetLightroomWindowID()

                                                  {

                                                      lr_win_id := 0

                                                      Process, Exist, lightroom.exe

                                                      lr_pid := ErrorLevel

                                                   

                                                      if lr_pid {

                                                          WinGet, id, list, ahk_pid %lr_pid%

                                                      } else {

                                                          WinGet, id, list,,, Program Manager

                                                      }

                                                      Loop, %id%

                                                      {

                                                          this_id := id%A_Index%

                                                   

                                                          WinGetClass, this_class, ahk_id %this_id%

                                                   

                                                          if (this_class = "AgWinMainFrame") {

                                                              ; MsgBox Got Lr Frame type

                                                          } else {

                                                              continue

                                                          }

                                                   

                                                          WinGetTitle, this_title, ahk_id %this_id%

                                                   

                                                          if InStr( this_title, "Lightroom" ) {

                                                              if (lr_win_id = 0) {

                                                   

                                                                  lr_win_id := this_id

                                                   

                                                              } else { ; redundent

                                                                  lr_win_id := 0

                                                                  break

                                                              }

                                                          }

                                                      }

                                                      return lr_win_id

                                                  }

                                                   

                                                   

                                                   

                                                  /*

                                                      Make sure Lightroom will be the recipient of emitted keystrokes.

                                                  */

                                                  LightroomActivate()

                                                  {

                                                      lr_win_id := GetLightroomWindowID()

                                                      if lr_win_id {

                                                          WinActivate, ahk_id %lr_win_id%

                                                          return 1

                                                      } else {

                                                          return 0 ; false

                                                      }

                                                  }

                                                   

                                                   

                                                   

                                                  if LightroomActivate() {

                                                      Send %1%

                                                  } else {

                                                      MsgBox Unable to activate Lightroom window.

                                                  }

                                                  • 22. Re: Lion & osascript
                                                    jarnoh Community Member

                                                    To create virtual copy on OSX, I just execute:

                                                     

                                                    osascript -e 'tell application "System Events"' -e "keystroke \"'\" using {command down}" -e 'end tell'

                                                     

                                                    I don't have to worry about activating window, because it is invoked from UI button.  Why this doesn't require assitive device permission is beyond my knowledge.

                                                     

                                                    On Windows, I wrote my own keyboard event stuffer in Win32 C++, it actually less lines than your AHK code

                                                    • 23. Re: Lion & osascript
                                                      areohbee Community Member

                                                      jarnoh wrote:

                                                       

                                                      To create virtual copy on OSX, I just execute:

                                                       

                                                      osascript -e 'tell application "System Events"' -e "keystroke \"'\" using {command down}" -e 'end tell'

                                                       

                                                      OK - so the difference is in activating the Lr window - thanks.

                                                       

                                                      I've got it (Window activation) built into the boiler plate code (not optional) so it works in more situations, but I agree - if it's being done immediately after invocation of a  menu function, then it's not so necessary. It makes me nervious though (to put it mildly) not to be sure where the keystrokes are going. I mean, even Outlook reminder popup etc. will take focus away from Lr, as can any number of other things, especially during long-running tasks - no telling what those keystrokes will do if they end up in the wrong box - maybe make a user very uneasy even if no damage done.

                                                       

                                                      PS - Glad you got a  solution for Windows too - but note: only one line of the AHK script sends the keys, the rest is WIndow activation, and I'm guessing you also fore-went that in your Windows app, right?

                                                       

                                                      Thanks again Jarno,

                                                      Rob

                                                      • 24. Re: Lion & osascript
                                                        jarnoh Community Member

                                                        Actually, I can also activate window without having assitive devices enabled, so that is not the real reason. 

                                                         

                                                        Sending key events to active window can of course fail with popup windows, but it is extremely unlikely, and it can also happen between AHK's activate and sendkeys methods.  It is much more likely that there is some other LR related problem, like running out of diskspace

                                                         

                                                        In case I don't get expected amount of virtual copies, I'm notifying the user.  Just wishing the LR5 undocumented method would work for all cases...

                                                         

                                                        And yes, Windows version just sends the keystrokes, I was just saying that it is not that much of code, no matter what tools you use.  I just prefer simpler techniques without additional dependencies, it is typically easier to debug them.

                                                        • 25. Re: Lion & osascript
                                                          areohbee Community Member

                                                          jarnoh wrote:

                                                           

                                                          I can also activate window without having assitive devices enabled, so that is not the real reason.

                                                          Maybe it's the bug where some users have to disable it then reenable it. Two users of my plugins have fixed the problem that way, and I've read of others (which is how I got the idea in the first place).

                                                           

                                                           

                                                          jarnoh wrote:

                                                           

                                                          it is extremely unlikely

                                                          If a plugin is executing and Lr main loses focus, the keystroke will be diverted, and it is possible, in some cases even probable, for Lr main to lose focus while a plugin is executing.

                                                           

                                                          R

                                                          • 26. Re: Lion & osascript
                                                            areohbee Community Member

                                                            Update:

                                                             

                                                            Mavericks and Yosemite have no such dialog box for enabling access by assistive devices (which is a pre-requisite for keyboard stuffing via applescript, or at least it has been for the scripts in the cases I've tested).

                                                             

                                                            Jacob Salmela has written this "white paper" which may help get the applescript-powered keyboard stuffing to work in Mavericks/Yosemite:

                                                             

                                                            http://jacobsalmela.com/os-x-yosemite-osascript-enabling-access-assistive-devices/

                                                             

                                                            Rob