5

I am attempting to open System Preferences from a Sandboxed macOS application, so that the user can manually enable a certain preference.

AppleScript activate

Brings an application to the front, launching it if necessary.

I am running macOS 10.13.6 and Xcode 10.0. The Deployment Target is set to OS X 10.11.

I run the following AppleScript from a sandboxed app:

let script = """
             tell application "System Preferences"
                 activate
                 set current pane to pane id "com.apple.preferences.extensions"
             end tell
             """
let appleScript = NSAppleScript(source: script)
var errorInfo: NSDictionary? = nil
appleScript?.executeAndReturnError(&errorInfo)

I also add a scripting targets Sandbox Entitlement enabling System Preferences to reveal panes:

<key>com.apple.security.scripting-targets</key>
<dict>
    <key>com.apple.systempreferences</key>
    <array>
        <string>preferencepane.reveal</string>
    </array>
</dict>

This somewhat works, once I add the Entitlement. The Systems Preferences app launches if closed and opens the correct pane.

The errorInfo dictionary is nil and presents no error info.

In the console I see a message, which is perhaps unrelated log spam:

AppleEvents: received mach msg which wasn't complex type as expected in getMemoryReference.

System Preferences window does not activate or come to foreground.

However, the app does not activate. The System Preferences window does not come to the front. The app navigates to the correct tab, but does not come to the foreground as the docs for activate state. It remains behind any other foreground windows.

In the case where System Preferences is closed, the app does launch. But the window is not added to the screen in the foreground or background until you click the dock icon. The window then appears, already navigated to the correct pane.

Why does the app not activate?

Are there any other needed Sandbox Entitlements that will allow for activation of the System Preferences window?

Community
  • 1
  • 1
pkamb
  • 33,281
  • 23
  • 160
  • 191
  • is your app is show in automation tab in privacy if not then first you need to add your app in system preferences – Ron Gahlot Sep 20 '18 at 08:07
  • @RonGahlot I'm seeing this issue in 10.13 linked against Xcode 10 / 10.14 SDK. I do not have that `Automation` tab in 10.13. – pkamb Sep 20 '18 at 15:47

2 Answers2

1

I suggest that you do the following (this was tested by me on macOS Mojave and works as intended).

  1. Open Script Editor
  2. Paste your script code into it (without the external quotes, of course)
  3. Save it as an app
  4. Go to the place in Finder where you saved it and with the right button click on "Show Package Contents".
  5. Go to Contents and the open Info.plist in Xcode
  6. Check the entitlements this app used, in particular the Privacy - AppleEvents Sending Usage Description (NSAppleEventsUsageDescription).
  7. Replicate that in your app, but please do not use all the entitlements this Applescript app uses by default, only the ones you really need.
pkamb
  • 33,281
  • 23
  • 160
  • 191
jvarela
  • 3,744
  • 1
  • 22
  • 43
  • I've created that app using Script Editor from macOS 10.13. The generated `info.plist` does not contain the `NSAppleEventsUsageDescription` key. It is not Sandboxed either. The script app **does** work correctly and activate the window, in addition to navigating to the correct pane. – pkamb Sep 20 '18 at 05:39
  • Adding a `NSAppleEventsUsageDescription` string value as suggested [on indiestack](https://indiestack.com/2018/08/apple-events-usage-description/) and [mjtsai blog](https://mjtsai.com/blog/2018/08/23/apple-events-usage-description/) to my main app does not cause the Apple Script to activate the window. – pkamb Sep 20 '18 at 05:41
  • Well, apparently, it is a bug in macOS 10.13, and daniel seemed to have given you a workaround. Anyway, this bug should be reported. Please do that at bugreport.apple.com. Thanks. – jvarela Sep 20 '18 at 21:44
  • Added as rdar://44661897 – pkamb Sep 21 '18 at 00:10
1

It seems like a bug to me that the activate command is not allowed from your script. However, I confirmed in a simple test application that even though I reproduce the behavior you described, the problem can be worked around by using NSWorkspace to launch System Preferences instead. This procedure has a side effect of activating the app if it is already launched. So, add code like this before your AppleScript executes:

NSWorkspace.shared.launchApplication(withBundleIdentifier: "com.apple.systempreferences", options: [], additionalEventParamDescriptor: nil, launchIdentifier: nil)

Something else weird: if you leave the "activate" in the script it seems to cause the running app to reactivate. So the complete workaround seems to require adding something like the above in code and removing the 'activate' from the script.

pkamb
  • 33,281
  • 23
  • 160
  • 191
danielpunkass
  • 17,527
  • 4
  • 24
  • 38
  • Yeah I'm currently using that same NSWorkspace launch workaround, including then needing to *remove* the `activate` command to avoid glitchy behavior. Works fine for this, but I am worried that I've now activated some 10.14-related AppleScript changes (as detailed in your [blog post](https://indiestack.com/2018/08/apple-events-usage-description/)) and this is only the first symptom. – pkamb Sep 20 '18 at 15:45