7

The following code is trying to open the proxies settings dialog,

 NSAppleScript *a = [[NSAppleScript alloc] initWithSource:@"tell application \"System Preferences\"\nset current pane to pane \"com.apple.preference.network\"\nactivate\nend tell\ntell application \"System Events\" to tell process \"System Preferences\" to tell window 1\n click button -3\nclick radio button -2 of tab group 1 of sheet 1\nend tell"];
    [a executeAndReturnError:nil];  

it has been working well until I upgrade my Mac OS to 10.9. The second part of the applescript,

 tell application \"System Events\" to tell process \"System Preferences\" to tell window 1\n click button -3\nclick radio button -2 of tab group 1 of sheet 1\nend tell 

it doesn't work any more. so if any one could tell me the reason, I would be very grateful.


edit: Here is my .entitlements file information,

  <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
    <key>com.apple.security.scripting-targets</key>
        <dict>
            <key>com.apple.preference</key>
            <array>
                <string>com.apple.preference</string>
                <string>com.apple.systemevents</string>
            </array>
        </dict>
    <key>com.apple.security.temporary-exception.apple-events</key>
        <array>
            <string>com.apple.preference</string>
            <string>com.apple.systemevents</string>
        </array>
</dict>
</plist>
mklement0
  • 382,024
  • 64
  • 607
  • 775
Grey
  • 253
  • 4
  • 15
  • but if I copy that applescript into AppleScript Editor and run it, everything is ok. – Grey Jan 23 '14 at 08:49
  • I suspect it is to do with sandboxing. read https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html – markhunte Jan 23 '14 at 11:05
  • @markhunte I set "com.apple.security.scripting-targets" and "com.apple.security.temporary-exception.apple-events" both in the .entitlements file, but it still doesn't work, should I add "com.apple.security.temporary-exception.apple-events" in the iTunes Connect, too? I haven't uploaded it to review yet. – Grey Jan 24 '14 at 08:46
  • I have updated my answer with a working solution – markhunte Jan 25 '14 at 00:12
  • @markhunte And did you add"com.apple.security.sandbox" ,too?? if you didn't ,all the others are meaningless.Even if the code works, the app is without sandbox. – Grey Jan 25 '14 at 07:56
  • :-). Yes I did. Is yours still not working? Also are you looking at the console.app logs to see if there are any Denys and what they are – markhunte Jan 25 '14 at 08:45
  • @markhunte ah..Now it works. Actually, I have two versions of the code, one is for objective-c(cocoa), the other is for C++(Qt), Changing that id to "com.apple.systempreferences" makes the former version work. As for the Qt one, it would start a process of "usr/bin/osascript" and let it execute the applescript. that's why it won't work after being sandboxed. – Grey Jan 25 '14 at 13:08

3 Answers3

5

UPDATE TO ANSWER

Ok after a little play with sandboxing which I have never used before: I used the option :

However, for applications that specifically provide scripting access groups, you can send appropriate Apple events to those apps if your app includes a scripting targets entitlement.

For other applications, by using a temporary exception entitlement, you can enable the sending of Apple events to a list of specific apps that you specify, as described in Entitlement Key Reference.

So in the Entitlements file.

You need to add the Entitlement:

com.apple.security.temporary-exception.apple-events

Set it as an Array

Then add two items to it.

com.apple.systempreferences

com.apple.systemevents

These items should be strings

Save the file.

This is All I have done and there are no other entitlements added

On my tests the System prefs opened and the Proxies tab was selected.

This also shows any App you that even if you tell one app to tell another app/process ..do something. Both apps must be in the list


A slight change to your setup should fix your issue:

By doing this I notice that in your edit you show you have added:

com.apple.preferences.

So you just need to change it to the correct id which is com.apple.systempreferences


Original part of Answer:


If you read the AboutAppSandbox link I provided you in the comments. Which I suggested as I assumed your app was sandboxed already. You should have seen:

Use of accessibility APIs in assistive apps With App Sandbox, you can and should enable your app for accessibility, as described in Accessibility Overview for OS X. However, you cannot sandbox an assistive app such as a screen reader, and you cannot sandbox an app that controls another app.

( I have literally just read this myself )

This implies with regards to accessibility APIs in assistive apps And sandoxing, you can do one or the other but not both.

There is however this bit also but you will need to investigate its implications

However, for applications that specifically provide scripting access groups, you can send appropriate Apple events to those apps if your app includes a scripting targets entitlement.

For other applications, by using a temporary exception entitlement, you can enable the sending of Apple events to a list of specific apps that you specify, as described in Entitlement Key Reference.

And reading further there is another possible approach

Finally, your app can use the subclasses of NSUserScriptTask class to run user-provided AppleScript scripts out of a special directory, NSApplicationScriptsDirectory (~/Library/Application Scripts/code-signing-identifier/). Although your app can read files within this directory, it cannot write files into this directory; the user must manually place scripts here. For details, see the documentation for NSUserScriptTask and WWDC 2012: Secure Automation Techniques in OS X.


The strategy you are using is not what I would want from an app. And I think using GUI like this leaves a lot of room for it to fail.Either because of element tree changes in the GUI or user interaction takes focus away from the intended target of the system events.

I think the better approach would be to inform the user to change the proxy their selves.

markhunte
  • 6,805
  • 2
  • 25
  • 44
3

New in Mavericks: the System Preferences app (bundle id: “com.apple.systempreferences”) has an access group (“preferencepane.reveal”); therefore you'll need to use this access group entitlement to be able to send the System Preference app the reveal command:

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

You can determine a scriptable applications access groups by using the sdef tool (see man page).

The Mac App Review team will most likely not grant you any scripting privileges that will allow you to script changing user defined preferences.

geowar
  • 4,397
  • 1
  • 28
  • 24
  • you are right, my app has been rejected by app store because of the entitlements "com.apple.security.temporary-exception.apple-events: com.apple.systemevents" AND "com.apple.security.temporary-exception.apple-events: com.apple.systempreferences" . – Grey Feb 14 '14 at 03:50
1

Those kind of scripts are secured by OS X. See "System Preferences", "Security & Privacy", "Accessibility". Here you can add apps that are allowed (or not) to control your computer. I guess you have to add your app here.

  • (…and since it's working within AppleScript-Editor I guess your AppleScript-Editor is already in that list of allowed apps) –  Jan 23 '14 at 16:22
  • You can drag your app into the list to add it there. –  Jan 24 '14 at 15:47