Scripting Bridge

RSS for tag

Automate scriptable apps by sending and receiving Apple events using Scripting Bridge.

Posts under Scripting Bridge tag

15 Posts

Post

Replies

Boosts

Views

Activity

Why do random errOSAInternalTableOverflow errors return when running AppleScripts via ScriptingBridge?
We have an app that controls InDesign Desktop and InDesignServer via hundreds of AppleScripts. Some macOS security updates a while back dictated that we start communicating with other apps via ScriptingBridge. We couldn't afford to convert the hundreds of AppleScripts into direct ScriptingBridge nomenclature, so we opted to keep them as is and instead tell the external apps to: [app doScript:<the script text> language:InDesignScLgApplescriptLanguage withArguments:nil undoMode:InDesignESUMScriptRequest undoName:@"blah"] There are a handful of scripts that we did convert to direct ScriptingBridge. There are times (and under the right circumstances, it's repeatable) when a certain script will have run perfectly dozens of times, and then it will throw errOSAInternalTableOverflow. We create a new SBApplication for every job (which could be a single instance of Desktop or the multiple instances of Server). Why is this error happening seemingly randomly? Is there anything we can do to work around or prevent this?
8
0
836
Apr ’26
Is calling different SBApplication objects from different threads bad?
Not quite but maybe sorta related to the errOSAInternalTableOverflow problem I asked about in a different thread, this one deals with crashes our app gets (and much more frequently lately after recent OS updates (15.7.3) are OK'd by our IT department). Our app can run multiple jobs concurrently, each in their own NSOperation. Each op creates its own SBApplication instance that controls unique instances of InDesignServer. What I'm seeing recently is lots of crashes happening while multiple ops are calling into ScriptingBridge. Shown at the bottom is one of the stack crawls from one of the threads. I've trimmed all but the last of our code. Other threads have a similar stack crawl. In searching for answers, Google's AI overview mentions "If you must use multiple threads, ensure that each thread creates its own SBApplication instance…" Which is what we do. No thread can reach another thread's SBApplication instance. Is that statement a lie? Do I need to lock around every ScriptingBridge call (which is going to severely slow things down)? 0 AE 0x1a7dba8d4 0x1a7d80000 + 239828 1 AE 0x1a7d826d8 AEProcessMessage + 3496 2 AE 0x1a7d8f210 0x1a7d80000 + 61968 3 AE 0x1a7d91978 0x1a7d80000 + 72056 4 AE 0x1a7d91764 0x1a7d80000 + 71524 5 CoreFoundation 0x1a0396a64 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 6 CoreFoundation 0x1a03969f8 __CFRunLoopDoSource0 + 172 7 CoreFoundation 0x1a0396764 __CFRunLoopDoSources0 + 232 8 CoreFoundation 0x1a03953b8 __CFRunLoopRun + 840 9 CoreFoundation 0x1a03949e8 CFRunLoopRunSpecific + 572 10 AE 0x1a7dbc108 0x1a7d80000 + 246024 11 AE 0x1a7d988fc AESendMessage + 4724 12 ScriptingBridge 0x1ecb652ac -[SBAppContext sendEvent:error:] + 80 13 ScriptingBridge 0x1ecb5eb4c -[SBObject sendEvent:id:keys:values:count:] + 216 14 ScriptingBridge 0x1ecb6890c -[SBCommandThunk invoke:] + 376 15 CoreFoundation 0x1a037594c ___forwarding___ + 956 16 CoreFoundation 0x1a03754d0 _CF_forwarding_prep_0 + 96 17 RRD 0x1027fca18 -[AppleScriptHelper runAppleScript:withSubstitutionValues:usingSBApp:] + 1036
21
0
1.4k
Mar ’26
Copying files using Finder and Apple Events
I need my application to copy some files, but using Finder. Now, I know all different methods and options to programmatically copy files using various APIs, but that's not the point here. I specifically need to use Finder for the purpose, so please, let's avoid eventual suggestions mentioning other ways to copy files. My first thought was to use the most simple approach, execute an AppleScript script using NSUserAppleScriptTask, but that turned out not to be ideal. It works fine, unless there already are files with same names at the copying destination. In such case, either the script execution ends with an error, reporting already existing files at the destination, or the existing files can be simply overridden by adding with overwrite option to duplicate command in the script. What I need is behaviour just like when Finder is used from the UI (drag'n'drop, copy/paste…); if there are existing files with same names at the destination, Finder should offer a "resolution panel", asking the user to "stop", "replace", "don't replace", "keep both" or "merge" (the latter in case of conflicting folders). So, I came to suspect that I could achieve such bahaviour by using Apple Events directly and passing kAEAlwaysInteract | kAECanSwitchLayer options to AESendMessage(). However, I can't figure out how to construct appropriate NSAppleEventDescriptor (nor old-style Carbon AppleEvent) objects and instruct Finder to copy files. This is where I came so far, providing srcFiles are source files (to be copied) URLs and dstFolder destination folder (to be copied into) URL: NSRunningApplication *finder = [[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"] firstObject]; if (!finder) { NSLog(@"Finder is not running."); return; } NSAppleEventDescriptor *finderDescriptor = [NSAppleEventDescriptor descriptorWithBundleIdentifier:[finder bundleIdentifier]]; NSAppleEventDescriptor *dstDescriptor = [NSAppleEventDescriptor descriptorWithString:[dstFolder path]]; NSAppleEventDescriptor *srcDescriptor = [NSAppleEventDescriptor listDescriptor]; for (NSURL *url in srcFiles) { NSAppleEventDescriptor *fileDescriptor = [NSAppleEventDescriptor descriptorWithString:[url path]]; [srcDescriptor insertDescriptor:fileDescriptor atIndex:([srcDescriptor numberOfItems] + 1)]; } NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kAECoreSuite eventID:kAEClone targetDescriptor:finderDescriptor returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [event setParamDescriptor:srcDescriptor forKeyword:keyDirectObject]; [event setParamDescriptor:dstDescriptor forKeyword:keyAETarget]; NSError *error; NSAppleEventDescriptor *result = [event sendEventWithOptions:(NSAppleEventSendAlwaysInteract | NSAppleEventSendCanSwitchLayer) timeout:10.0 error:&error]; The code above executes without any error. The final result descriptor is a NULL descriptor ([NSAppleEventDescriptor nullDescriptor]) and there's no error returned (by reference). However, nothing happens, Finder remains silent and the application doesn't make macOS/TCC prompt for a permission to "automate Finder". I wonder if the approach above is correct and if I use correct parameters as arguments for all calling method/messages. I'm specially interested if passing keyAETarget is the right value in [event setParamDescriptor:dstDescriptor forKeyword:keyAETarget], since that one looks most suspicious to me. I'd really appreciate if anyone can help me with this. I'd also like to point out that I tried the same approach outlined above with old-style Carbon AppleEvent API, using AECreateDesc(), AECreateAppleEvent(), AEPutParamDesc() and AESendMessage()… All API calls succeeded, returning noErr, but again, nothing happened, Finder remained silent and no macOS/TCC prompt for a permission to "automate Finder". Any help is highly appreciated, thanks! -- Dragan
9
0
605
Oct ’25
Apple Music ScriptingBridge Broken in macOS Tahoe 26
l’m trying to automate Apple Music on macOS Tahoe 26 using ScriptingBridge. Scripts that previously worked for controlling playback, fetching track info, or manipulating playlists no longer function. For example, code like this used to work: `import ScriptingBridge let music = SBApplication(bundleIdentifier: "com.apple.Music") as! MusicApplication print(music.currentTrack?.name ?? "No track playing")` But now it fails, returning nil for track info and failing to send playback commands. Questions: Has ScriptingBridge been deprecated or broken in Tahoe 26 for Apple Music? Any guidance or example code would be appreciated.
2
2
518
Oct ’25
Not authorized to send Apple events to Microsoft Excel
I have created swift command line project and i have added logic to executing apple script using NSAppleScript. That will launch Microsoft Excel file I am launching this swift command line executable from java using process launch. 3)This is not prompting me. It is throwing exception "Not authorized to send Apple events to Microsoft Excel." I have already tried out this option Added info.plist with NSAppleEventsUsageDescription Added entitlement with com.apple.security.automation.apple-events to true In packages i have selected this entitlement i have select the bundle identifier , team and signing certificate "Development" and automatically manage signing. can you please suggest what could i missed ?
1
0
653
Dec ’24
Getting path of deleted item from Scripting Bridge SBObject in Swift
In the Swift function at the end of this post, I use Scripting Bridge to have Finder delete a path. The variable result is a SBObject returned by the delete() function. I know that result somehow contains the new path of the deleted item in the trash folder, but I don't know how to nicely extract it as a single String. If I print(String(describing: result)), I get output like: <SBObject @0x0123456789ab: <class 'appf'> "AppName.app" of <class 'cfol'> ".Trash" of <class 'cfol'> "user" of <class 'cfol'> "Users" of startupDisk of application "Finder" (822)> Is there any way to obtain the String "/Users/user/.Trash/AppName.app" from result without having to perform string parsing on the above output? The Finder* types in the code below are from https://github.com/tingraldi/SwiftScripting/blob/master/Frameworks/FinderScripting/FinderScripting/Finder.swift func trash(path: String) throws { guard let finder: FinderApplication = SBApplication(bundleIdentifier: "com.apple.finder") else { throw runtimeError("Failed to obtain Finder access: com.apple.finder does not exist") } guard let items = finder.items else { throw runtimeError("Failed to obtain Finder access: finder.items does not exist") } let object = items().object(atLocation: URL(fileURLWithPath: path)) guard let item = object as? FinderItem else { throw runtimeError( """ Failed to obtain Finder access: finder.items().object(atLocation: URL(fileURLWithPath: \ \"\(path)\") is a '\(type(of: object))' that does not conform to 'FinderItem' """ ) } guard let delete = item.delete else { throw runtimeError("Failed to obtain Finder access: FinderItem.delete does not exist") } let result = delete() }
2
0
768
Oct ’24
Trouble with AppleScript Permissions and ShazamKit Integration in macOS App
Hello fellow developers, I am developing a macOS app called "Playlist Plunderer 2," aimed at using AppleScript to control the Music app to play songs and employing ShazamKit to recognize these songs and update their metadata. Despite setting up the entitlements and plist files correctly, I'm encountering issues with gaining the necessary AppleScript permissions, and my app is not appearing under 'Automation' in System Preferences. Additionally, ShazamKit fails to match songs, consistently returning error 201. Here are the specifics of my setup and what I've tried so far: Xcode Version: 15.4, macOS 14.1.2 Entitlements Configured: Includes permissions for Apple events, audio input, and scripting targets for the Music app. Capabilities: ShazamKit and ScriptingBridge frameworks integrated, set to "Do Not Embed." Info.plist Adjustments: Added "Privacy - Microphone Usage Description." Scripting: Manual AppleScript commands outside of Xcode succeed, but the app's scripts do not trigger. Entitlements File: <?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.automation.apple-events</key> <true/> <key>com.apple.security.device.audio-input</key> <true/> <key>com.apple.security.files.user-selected.read-only</key> <true/> <key>com.apple.security.scripting-targets</key> <dict> <key>com.apple.Music</key> <array> <string>com.apple.Music.playback</string> <string>com.apple.Music.library.read-write</string> </array> </dict> </dict> </plist> I am having issues controlling the music app (itunes) from the apple script within my xcode project. the objective of the app is to rewrite the metadata of songs inside a folder in my Music app, this folder is titled Playlist Plunderer. The way I intend for the app to function is, the app will play the songs in the playlist, and then it will use shazamkit to recognize the song thats playing, it will then copy the metadata results of that song to rewrite the metadata of the song in the music playlist. I am still in the beginning stages. and I am very new to xcode. I created a apple developer account, paid the $99 and it is active, and I added the identifier bundle to the account from my app. I am VERY new to xcode,(this is my first project) my development team is set ( Shane Vincent), and the app is set to automatically manage signing, under app sandbox. i have audio input checked, under hardened runtime/ resource access audio input is checked. in build settings the path to the info.plist file is correct, the info.plist contains Privacy - Microphone Usage Description that I added i think it was called NSMmicriphone or something, with a description that reads "This app needs to access the microphone to identify songs using ShazamKit." the app appears under System Preferences > Security & Privacy > Privacy > Microphone but not under System Preferences > Security & Privacy > Privacy > Automation it is being made on macOS 14.1.2 (23B92) and xcode Version 15.4 (15F31d) Under framework library, and embedded content, I have added two frameworks, Shazamkit.framework, and ScriptingBridge.framework, both set to do not embed Current Issue: AppleScript fails to authorize with the Music app, and ShazamKit errors suggest an issue with song matching. Has anyone faced similar challenges or can offer guidance on how to ensure AppleScript and ShazamKit function correctly within a sandboxed macOS app? Any insights into troubleshooting or configuring entitlements more effectively would be greatly appreciated. Thanks for your help!
3
0
1.1k
Jul ’24
Capture all inbuilt trackpad events and cancel some touch events
I'm trying to capture all trackpad events at OS level and disable few of them - say the ones in left half of trackpad. Following this question, I could level listen to events in current window view with following code. final class AppKitTouchesView: NSView { override init(frame frameRect: NSRect) { super.init(frame: frameRect) // We're interested in `.indirect` touches only. allowedTouchTypes = [.indirect] // We'd like to receive resting touches as well. wantsRestingTouches = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func handleTouches(with event: NSEvent) { // 1. Change `in` parameter to listen events at OS level // 2. Disable all events with `touch.normalizedPosition.x < 0.5` let touches = event.touches(matching: .touching, in: self) } override func touchesBegan(with event: NSEvent) { handleTouches(with: event) } override func touchesEnded(with event: NSEvent) { handleTouches(with: event) } override func touchesMoved(with event: NSEvent) { handleTouches(with: event) } override func touchesCancelled(with event: NSEvent) { handleTouches(with: event) } } I'd to accomplish two things further. Change in parameter to listen events at OS level Disable all touch events on some condition - say touch.normalizedPosition.x < 0.5
0
0
721
Jul ’24
Can't write a property through ScriptingBridge
Staring to use ScriptingBridge in Swift to enable faster scripting access to an external app (Devonthink) and therefore avoid having to use an AppleScript as a conduit to call a Swift command line utility and deal with its results. The plan is to be able to read the plaintext of a record (no problem) and change the record name in Devonthink based on its contents. But I can’t seem to write to a property, instead getting an error “Cannot assign to property: ‘***’ is immutable”. Any guidance how to get around this?
2
0
837
Jun ’24
tccd reports Apple Events entitlement check error, despite a process having it
HI! I am developing an application that should utilize ScriptingBridge.framework to interact with another process. Firstly, I created a separate test application for which I have added Apple Events entitlements via "Signing & Capabilities" section in Xcode and updated its Info.plist to have "Privacy - AppleEvents Sending Usage Description". While the test app works fine (I see an automation request popup and the process executes as expected) the main application where I want to integrate this functionality gets closed immediately after reaching the code interacting with Scripting Bridge. On its launch, I see the following error message from tccd in Console: Prompting policy for hardened runtime; service: kTCCServiceAppleEvents requires entitlement com.apple.security.automation.apple-events but it is missing for accessing={TCCDProcess: identifier=<app bundleID>, ..., binary_path=<path to the app's binary>} I had no such issues with the test app. Moreover, I should mention that the bundle I want to have with such functionality is stored in another bundle, both main and inner bundles aren't sandboxed, and the target app has Application is agent (UIElement) key set in Info.plist. Can you suggest any ideas as to why processes behave so differently despite having pretty much the same build configurations?
14
1
2k
Jun ’24
How to listen for Privacy & Security > Automation > System Events status changes in MacOS Swift
My project (an non-sandbox app) was written in Swift on MacOS and it can execute the Apple script successfully. I would like to listen for Privacy &amp; Security &gt; Automation &gt; System Events status changes when the user changes it in System Settings to disable or enable my app feature in MacOS. My app can receive Accessibility changes through this notification "com.apple.accessibility.api" Are there any system notifications for my app to receive Automation &gt; System Events status changes? Thank you!
2
1
1.2k
Mar ’24
Send event: errAEPrivilegeError -10004
Could you please help me to solve the problem or give the advice? I am trying to send an apple event and get a response asynchronously. Here is the example code for sending the apple event: let target = NSAppleEventDescriptor(applicationURL: URL(string: “eppc://userName:password@ip/appName”)!) let appleEvent = NSAppleEventDescriptor(eventClass: AEEventClass(stringLiteral: “test”), eventID: AEEventID(stringLiteral: “evnt”), targetDescriptor: target, returnID: AEReturnID(kAutoGenerateReturnID), transactionID: AETransactionID(kAnyTransactionID)) let resultEvent = try appleEvent.sendEvent(options: [.queueReply], timeout: TimeInterval(kNoTimeOut)) Here is what the event handler looks like in the target application: @objc func handler(event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) { try replyEvent!.sendEvent(options: [.noReply], timeout: TimeInterval(kNoTimeOut)) } I encountered two difficulties using the ‘queueReply’ sending mode: I see the input window for credentials in the case when the event handler app tries to send the response to the sender app. (This is a problem for me since there is no one to enter the password on the side of the handler app. This window for credentials entry is not displayed if the sending is in the “waitForReply” mode) After entering the correct credentials, the sender app receives the error AppleEvents/sandbox: Returning errAEPrivilegeError/-10004 Sender app logs: {test,evnt target=aprl(38/$657070633a2f2f3139322e3136382e302e3131352f6170706c654576656e7448...) {} returnID=27646} 2023-02-20 15:42:24.045320+0200 testevents[41720:2641106] [main] ERROR: AEImpl::~AEImpl fRetainCount not zero (1) {aevt,ansr target=aprl(38/$657070633a2f2f3139322e3136382e302e3131352f6170706c654576656e7448...) {} returnID=27646} 2023-02-20 15:42:29.593044+0200 testevents[41720:2641063] Suite NSCoreSuite, apple event code 0x1061109567x 2023-02-20 15:42:29.595201+0200 testevents[41720:2641063] Suite NSTextSuite, apple event code 0x1061109567x 2023-02-20 15:42:29.840410+0200 testevents[41720:2641063] [main] AppleEvents/sandbox: Returning errAEPrivilegeError/-10004 and denying dispatch of event aevt/ansr from process ‘’/0x0-0x0, pid=0, because it is not entitled to send the AppleEvent to this process. Handler app logs: {test,evnt target=aprl(27/$657070633a2f2f3139322e3136382e302e3131353a35393037362f) {}} {aevt,ansr target=aprl(27/$657070633a2f2f3139322e3136382e302e3131353a35393037362f) {}} 2023-02-20 15:42:29.569897+0200 appleEventHandler[41454:2635163] [main] ERROR: AEImpl::~AEImpl fRetainCount not zero (1) 2023-02-20 15:42:29.576049+0200 appleEventHandler[41454:2640788] [connection] nw_socket_handle_socket_event [C4:1] Socket SO_ERROR [61: Connection refused] 2023-02-20 15:42:29.577080+0200 appleEventHandler[41454:2638578] [connection] nw_connection_get_connected_socket [C4] Client called nw_connection_get_connected_socket on unconnected nw_connection ... In this case, the sender app receives the response but is not handled. Handler code: NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handler), forEventClass: AEEventClass(stringLiteral: “aevt”), andEventID: AEEventID(stringLiteral: “ansr”)) @objc func handler(_ event: NSAppleEventDescriptor?, withReplyEvent: NSAppleEventDescriptor?) throws { print(event?.description) } But this code works correctly with: let target = NSAppleEventDescriptor(bundleIdentifier: “test.com.appleEventHandler”) Logs: {test,evnt target=bund(26/$746573742e636f6d2e6170706c654576656e7448616e646c6572) {} returnID=3183} {aevt,ansr target=appleEventHandler {} returnID=3183} Optional(“&lt;NSAppleEventDescriptor: \‘aevt\’\\‘ansr\’{ }&gt;“) {aevt,ansr target=appleEventHandler {} returnID=3183} Optional(“&lt;NSAppleEventDescriptor: \‘aevt\’\\‘ansr\’{ }&gt;“) Please help me to understand how can I get an async response using the send option “queueReply” by eppc? (“waitForReply” option works correctly with eppc in this code)
7
0
1.3k
Mar ’23
orderWindows not reliable/changed in Ventura
My application can be controlled by scripts using AppleScript, python (through scripting bridge), or my own internal scripting language in a script thread. I just noticed that scripts that need to know the current front window have stopped working in Ventura. I find the front window as the first relevant window in [NSApp orderedWindows] (in Objective C). I found the problem with Ventura by adding some debugging output as follows: Run a script thread to control my application When a new window is needed, this thread uses performSelectorOnMainThread to create a window and waits for it to appear and to get added to the document. Before returning from main thread selector, the ordered windows are checked and they are correct (the new window is an AncestorController). DEBUG: check window order after creating an AncestorController DEBUG: frontGEDCOMController windows are: ...1 of 2 <NSWindow: 0x123691e20> <AncestorController: 0x600001fc50e0> ...2 of 2 <NSWindow: 0x123641ad0> <IndexController: 0x6000019c0c40> ...current front window is AncestorController Immediately on return to script thread, however, another performSelectorOnMainThread is called to check the order of the windows again and it has changed in an instant to the wrong order (wrong because the AncestorController is still in front). DEBUG: recheck window order after 0.000000 seconds DEBUG: frontGEDCOMController windows are: ...1 of 2 <NSWindow: 0x123641ad0> <IndexController: 0x6000019c0c40> ...2 of 2 <NSWindow: 0x123691e20> <AncestorController: 0x600001fc50e0> ...front window type is IndexController But, if I sleep the thread, the order changes back to correct order in <= 1/30 second DEBUG: recheck window order after 0.033333 seconds DEBUG: frontGEDCOMController windows are: ...1 of 2 <NSWindow: 0x123691e20> <AncestorController: 0x600001fc50e0> ...2 of 2 <NSWindow: 0x123641ad0> <IndexController: 0x6000019c0c40> ... front window type is AncestorController This issue is new to Ventura. For some reason Ventura adds a window to the list in the correct position. It then movies to the wrong possible for a short amount of time before then returning to the correct position. That did not happen in MacOS 12.x or earlier. Now maybe I can find all the places my scripts that need to pause for Ventura to get things right, but it would be better to know why it has happened and then know where I need to insert Ventura hacks? Or is there another way that can reliably get ordered windows in Ventura? Curiously this problem does not occur when scripting by AppleScript. Maybe that is just so slow that pauses happen all the time anyway. I did find an alternative method to get ordered windows introduced in 10.12: enumerateWindowsWithOptions:usingBlock: with option NSWindowListOrderedFrontToBack but it is identical to using orderedWindows (i.e., gets the order wrong for a while).
0
0
1.1k
Dec ’22
Sending file parameters to a Shortcut on Monterey programmatically?
I'm trying to run Shortcuts programmatically on Monterey. My understanding is that the official API for this is via AppleScript to the Shortcuts Events process. I created a Shortcut that does Quicklook on the passed in file parameter. It works as a Finder action but I can't figure out how to get it to work when running it via AppleScript or Scripting Bridge. If I send a file, alias or POSIX file, I get a generic Shortcuts error 4. If I send a path as a string, it just does a preview of the string passed in, and not the contents of the file the path references. Anyone have any insight on how to get this working?
0
0
957
Sep ’21
Why do random errOSAInternalTableOverflow errors return when running AppleScripts via ScriptingBridge?
We have an app that controls InDesign Desktop and InDesignServer via hundreds of AppleScripts. Some macOS security updates a while back dictated that we start communicating with other apps via ScriptingBridge. We couldn't afford to convert the hundreds of AppleScripts into direct ScriptingBridge nomenclature, so we opted to keep them as is and instead tell the external apps to: [app doScript:<the script text> language:InDesignScLgApplescriptLanguage withArguments:nil undoMode:InDesignESUMScriptRequest undoName:@"blah"] There are a handful of scripts that we did convert to direct ScriptingBridge. There are times (and under the right circumstances, it's repeatable) when a certain script will have run perfectly dozens of times, and then it will throw errOSAInternalTableOverflow. We create a new SBApplication for every job (which could be a single instance of Desktop or the multiple instances of Server). Why is this error happening seemingly randomly? Is there anything we can do to work around or prevent this?
Replies
8
Boosts
0
Views
836
Activity
Apr ’26
Is calling different SBApplication objects from different threads bad?
Not quite but maybe sorta related to the errOSAInternalTableOverflow problem I asked about in a different thread, this one deals with crashes our app gets (and much more frequently lately after recent OS updates (15.7.3) are OK'd by our IT department). Our app can run multiple jobs concurrently, each in their own NSOperation. Each op creates its own SBApplication instance that controls unique instances of InDesignServer. What I'm seeing recently is lots of crashes happening while multiple ops are calling into ScriptingBridge. Shown at the bottom is one of the stack crawls from one of the threads. I've trimmed all but the last of our code. Other threads have a similar stack crawl. In searching for answers, Google's AI overview mentions "If you must use multiple threads, ensure that each thread creates its own SBApplication instance…" Which is what we do. No thread can reach another thread's SBApplication instance. Is that statement a lie? Do I need to lock around every ScriptingBridge call (which is going to severely slow things down)? 0 AE 0x1a7dba8d4 0x1a7d80000 + 239828 1 AE 0x1a7d826d8 AEProcessMessage + 3496 2 AE 0x1a7d8f210 0x1a7d80000 + 61968 3 AE 0x1a7d91978 0x1a7d80000 + 72056 4 AE 0x1a7d91764 0x1a7d80000 + 71524 5 CoreFoundation 0x1a0396a64 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 6 CoreFoundation 0x1a03969f8 __CFRunLoopDoSource0 + 172 7 CoreFoundation 0x1a0396764 __CFRunLoopDoSources0 + 232 8 CoreFoundation 0x1a03953b8 __CFRunLoopRun + 840 9 CoreFoundation 0x1a03949e8 CFRunLoopRunSpecific + 572 10 AE 0x1a7dbc108 0x1a7d80000 + 246024 11 AE 0x1a7d988fc AESendMessage + 4724 12 ScriptingBridge 0x1ecb652ac -[SBAppContext sendEvent:error:] + 80 13 ScriptingBridge 0x1ecb5eb4c -[SBObject sendEvent:id:keys:values:count:] + 216 14 ScriptingBridge 0x1ecb6890c -[SBCommandThunk invoke:] + 376 15 CoreFoundation 0x1a037594c ___forwarding___ + 956 16 CoreFoundation 0x1a03754d0 _CF_forwarding_prep_0 + 96 17 RRD 0x1027fca18 -[AppleScriptHelper runAppleScript:withSubstitutionValues:usingSBApp:] + 1036
Replies
21
Boosts
0
Views
1.4k
Activity
Mar ’26
Copying files using Finder and Apple Events
I need my application to copy some files, but using Finder. Now, I know all different methods and options to programmatically copy files using various APIs, but that's not the point here. I specifically need to use Finder for the purpose, so please, let's avoid eventual suggestions mentioning other ways to copy files. My first thought was to use the most simple approach, execute an AppleScript script using NSUserAppleScriptTask, but that turned out not to be ideal. It works fine, unless there already are files with same names at the copying destination. In such case, either the script execution ends with an error, reporting already existing files at the destination, or the existing files can be simply overridden by adding with overwrite option to duplicate command in the script. What I need is behaviour just like when Finder is used from the UI (drag'n'drop, copy/paste…); if there are existing files with same names at the destination, Finder should offer a "resolution panel", asking the user to "stop", "replace", "don't replace", "keep both" or "merge" (the latter in case of conflicting folders). So, I came to suspect that I could achieve such bahaviour by using Apple Events directly and passing kAEAlwaysInteract | kAECanSwitchLayer options to AESendMessage(). However, I can't figure out how to construct appropriate NSAppleEventDescriptor (nor old-style Carbon AppleEvent) objects and instruct Finder to copy files. This is where I came so far, providing srcFiles are source files (to be copied) URLs and dstFolder destination folder (to be copied into) URL: NSRunningApplication *finder = [[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"] firstObject]; if (!finder) { NSLog(@"Finder is not running."); return; } NSAppleEventDescriptor *finderDescriptor = [NSAppleEventDescriptor descriptorWithBundleIdentifier:[finder bundleIdentifier]]; NSAppleEventDescriptor *dstDescriptor = [NSAppleEventDescriptor descriptorWithString:[dstFolder path]]; NSAppleEventDescriptor *srcDescriptor = [NSAppleEventDescriptor listDescriptor]; for (NSURL *url in srcFiles) { NSAppleEventDescriptor *fileDescriptor = [NSAppleEventDescriptor descriptorWithString:[url path]]; [srcDescriptor insertDescriptor:fileDescriptor atIndex:([srcDescriptor numberOfItems] + 1)]; } NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kAECoreSuite eventID:kAEClone targetDescriptor:finderDescriptor returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [event setParamDescriptor:srcDescriptor forKeyword:keyDirectObject]; [event setParamDescriptor:dstDescriptor forKeyword:keyAETarget]; NSError *error; NSAppleEventDescriptor *result = [event sendEventWithOptions:(NSAppleEventSendAlwaysInteract | NSAppleEventSendCanSwitchLayer) timeout:10.0 error:&error]; The code above executes without any error. The final result descriptor is a NULL descriptor ([NSAppleEventDescriptor nullDescriptor]) and there's no error returned (by reference). However, nothing happens, Finder remains silent and the application doesn't make macOS/TCC prompt for a permission to "automate Finder". I wonder if the approach above is correct and if I use correct parameters as arguments for all calling method/messages. I'm specially interested if passing keyAETarget is the right value in [event setParamDescriptor:dstDescriptor forKeyword:keyAETarget], since that one looks most suspicious to me. I'd really appreciate if anyone can help me with this. I'd also like to point out that I tried the same approach outlined above with old-style Carbon AppleEvent API, using AECreateDesc(), AECreateAppleEvent(), AEPutParamDesc() and AESendMessage()… All API calls succeeded, returning noErr, but again, nothing happened, Finder remained silent and no macOS/TCC prompt for a permission to "automate Finder". Any help is highly appreciated, thanks! -- Dragan
Replies
9
Boosts
0
Views
605
Activity
Oct ’25
Apple Music ScriptingBridge Broken in macOS Tahoe 26
l’m trying to automate Apple Music on macOS Tahoe 26 using ScriptingBridge. Scripts that previously worked for controlling playback, fetching track info, or manipulating playlists no longer function. For example, code like this used to work: `import ScriptingBridge let music = SBApplication(bundleIdentifier: "com.apple.Music") as! MusicApplication print(music.currentTrack?.name ?? "No track playing")` But now it fails, returning nil for track info and failing to send playback commands. Questions: Has ScriptingBridge been deprecated or broken in Tahoe 26 for Apple Music? Any guidance or example code would be appreciated.
Replies
2
Boosts
2
Views
518
Activity
Oct ’25
Not authorized to send Apple events to Microsoft Excel
I have created swift command line project and i have added logic to executing apple script using NSAppleScript. That will launch Microsoft Excel file I am launching this swift command line executable from java using process launch. 3)This is not prompting me. It is throwing exception "Not authorized to send Apple events to Microsoft Excel." I have already tried out this option Added info.plist with NSAppleEventsUsageDescription Added entitlement with com.apple.security.automation.apple-events to true In packages i have selected this entitlement i have select the bundle identifier , team and signing certificate "Development" and automatically manage signing. can you please suggest what could i missed ?
Replies
1
Boosts
0
Views
653
Activity
Dec ’24
Getting path of deleted item from Scripting Bridge SBObject in Swift
In the Swift function at the end of this post, I use Scripting Bridge to have Finder delete a path. The variable result is a SBObject returned by the delete() function. I know that result somehow contains the new path of the deleted item in the trash folder, but I don't know how to nicely extract it as a single String. If I print(String(describing: result)), I get output like: <SBObject @0x0123456789ab: <class 'appf'> "AppName.app" of <class 'cfol'> ".Trash" of <class 'cfol'> "user" of <class 'cfol'> "Users" of startupDisk of application "Finder" (822)> Is there any way to obtain the String "/Users/user/.Trash/AppName.app" from result without having to perform string parsing on the above output? The Finder* types in the code below are from https://github.com/tingraldi/SwiftScripting/blob/master/Frameworks/FinderScripting/FinderScripting/Finder.swift func trash(path: String) throws { guard let finder: FinderApplication = SBApplication(bundleIdentifier: "com.apple.finder") else { throw runtimeError("Failed to obtain Finder access: com.apple.finder does not exist") } guard let items = finder.items else { throw runtimeError("Failed to obtain Finder access: finder.items does not exist") } let object = items().object(atLocation: URL(fileURLWithPath: path)) guard let item = object as? FinderItem else { throw runtimeError( """ Failed to obtain Finder access: finder.items().object(atLocation: URL(fileURLWithPath: \ \"\(path)\") is a '\(type(of: object))' that does not conform to 'FinderItem' """ ) } guard let delete = item.delete else { throw runtimeError("Failed to obtain Finder access: FinderItem.delete does not exist") } let result = delete() }
Replies
2
Boosts
0
Views
768
Activity
Oct ’24
Trouble with AppleScript Permissions and ShazamKit Integration in macOS App
Hello fellow developers, I am developing a macOS app called "Playlist Plunderer 2," aimed at using AppleScript to control the Music app to play songs and employing ShazamKit to recognize these songs and update their metadata. Despite setting up the entitlements and plist files correctly, I'm encountering issues with gaining the necessary AppleScript permissions, and my app is not appearing under 'Automation' in System Preferences. Additionally, ShazamKit fails to match songs, consistently returning error 201. Here are the specifics of my setup and what I've tried so far: Xcode Version: 15.4, macOS 14.1.2 Entitlements Configured: Includes permissions for Apple events, audio input, and scripting targets for the Music app. Capabilities: ShazamKit and ScriptingBridge frameworks integrated, set to "Do Not Embed." Info.plist Adjustments: Added "Privacy - Microphone Usage Description." Scripting: Manual AppleScript commands outside of Xcode succeed, but the app's scripts do not trigger. Entitlements File: <?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.automation.apple-events</key> <true/> <key>com.apple.security.device.audio-input</key> <true/> <key>com.apple.security.files.user-selected.read-only</key> <true/> <key>com.apple.security.scripting-targets</key> <dict> <key>com.apple.Music</key> <array> <string>com.apple.Music.playback</string> <string>com.apple.Music.library.read-write</string> </array> </dict> </dict> </plist> I am having issues controlling the music app (itunes) from the apple script within my xcode project. the objective of the app is to rewrite the metadata of songs inside a folder in my Music app, this folder is titled Playlist Plunderer. The way I intend for the app to function is, the app will play the songs in the playlist, and then it will use shazamkit to recognize the song thats playing, it will then copy the metadata results of that song to rewrite the metadata of the song in the music playlist. I am still in the beginning stages. and I am very new to xcode. I created a apple developer account, paid the $99 and it is active, and I added the identifier bundle to the account from my app. I am VERY new to xcode,(this is my first project) my development team is set ( Shane Vincent), and the app is set to automatically manage signing, under app sandbox. i have audio input checked, under hardened runtime/ resource access audio input is checked. in build settings the path to the info.plist file is correct, the info.plist contains Privacy - Microphone Usage Description that I added i think it was called NSMmicriphone or something, with a description that reads "This app needs to access the microphone to identify songs using ShazamKit." the app appears under System Preferences > Security & Privacy > Privacy > Microphone but not under System Preferences > Security & Privacy > Privacy > Automation it is being made on macOS 14.1.2 (23B92) and xcode Version 15.4 (15F31d) Under framework library, and embedded content, I have added two frameworks, Shazamkit.framework, and ScriptingBridge.framework, both set to do not embed Current Issue: AppleScript fails to authorize with the Music app, and ShazamKit errors suggest an issue with song matching. Has anyone faced similar challenges or can offer guidance on how to ensure AppleScript and ShazamKit function correctly within a sandboxed macOS app? Any insights into troubleshooting or configuring entitlements more effectively would be greatly appreciated. Thanks for your help!
Replies
3
Boosts
0
Views
1.1k
Activity
Jul ’24
Capture all inbuilt trackpad events and cancel some touch events
I'm trying to capture all trackpad events at OS level and disable few of them - say the ones in left half of trackpad. Following this question, I could level listen to events in current window view with following code. final class AppKitTouchesView: NSView { override init(frame frameRect: NSRect) { super.init(frame: frameRect) // We're interested in `.indirect` touches only. allowedTouchTypes = [.indirect] // We'd like to receive resting touches as well. wantsRestingTouches = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func handleTouches(with event: NSEvent) { // 1. Change `in` parameter to listen events at OS level // 2. Disable all events with `touch.normalizedPosition.x < 0.5` let touches = event.touches(matching: .touching, in: self) } override func touchesBegan(with event: NSEvent) { handleTouches(with: event) } override func touchesEnded(with event: NSEvent) { handleTouches(with: event) } override func touchesMoved(with event: NSEvent) { handleTouches(with: event) } override func touchesCancelled(with event: NSEvent) { handleTouches(with: event) } } I'd to accomplish two things further. Change in parameter to listen events at OS level Disable all touch events on some condition - say touch.normalizedPosition.x < 0.5
Replies
0
Boosts
0
Views
721
Activity
Jul ’24
Can't write a property through ScriptingBridge
Staring to use ScriptingBridge in Swift to enable faster scripting access to an external app (Devonthink) and therefore avoid having to use an AppleScript as a conduit to call a Swift command line utility and deal with its results. The plan is to be able to read the plaintext of a record (no problem) and change the record name in Devonthink based on its contents. But I can’t seem to write to a property, instead getting an error “Cannot assign to property: ‘***’ is immutable”. Any guidance how to get around this?
Replies
2
Boosts
0
Views
837
Activity
Jun ’24
tccd reports Apple Events entitlement check error, despite a process having it
HI! I am developing an application that should utilize ScriptingBridge.framework to interact with another process. Firstly, I created a separate test application for which I have added Apple Events entitlements via "Signing & Capabilities" section in Xcode and updated its Info.plist to have "Privacy - AppleEvents Sending Usage Description". While the test app works fine (I see an automation request popup and the process executes as expected) the main application where I want to integrate this functionality gets closed immediately after reaching the code interacting with Scripting Bridge. On its launch, I see the following error message from tccd in Console: Prompting policy for hardened runtime; service: kTCCServiceAppleEvents requires entitlement com.apple.security.automation.apple-events but it is missing for accessing={TCCDProcess: identifier=<app bundleID>, ..., binary_path=<path to the app's binary>} I had no such issues with the test app. Moreover, I should mention that the bundle I want to have with such functionality is stored in another bundle, both main and inner bundles aren't sandboxed, and the target app has Application is agent (UIElement) key set in Info.plist. Can you suggest any ideas as to why processes behave so differently despite having pretty much the same build configurations?
Replies
14
Boosts
1
Views
2k
Activity
Jun ’24
How to listen for Privacy & Security > Automation > System Events status changes in MacOS Swift
My project (an non-sandbox app) was written in Swift on MacOS and it can execute the Apple script successfully. I would like to listen for Privacy &amp; Security &gt; Automation &gt; System Events status changes when the user changes it in System Settings to disable or enable my app feature in MacOS. My app can receive Accessibility changes through this notification "com.apple.accessibility.api" Are there any system notifications for my app to receive Automation &gt; System Events status changes? Thank you!
Replies
2
Boosts
1
Views
1.2k
Activity
Mar ’24
Check for a new mail (macos)
Hi, How is it possible to check if I have a new mail? Is it possible to do it with ScriptingBridge? Thank you!
Replies
1
Boosts
0
Views
802
Activity
Jan ’24
Send event: errAEPrivilegeError -10004
Could you please help me to solve the problem or give the advice? I am trying to send an apple event and get a response asynchronously. Here is the example code for sending the apple event: let target = NSAppleEventDescriptor(applicationURL: URL(string: “eppc://userName:password@ip/appName”)!) let appleEvent = NSAppleEventDescriptor(eventClass: AEEventClass(stringLiteral: “test”), eventID: AEEventID(stringLiteral: “evnt”), targetDescriptor: target, returnID: AEReturnID(kAutoGenerateReturnID), transactionID: AETransactionID(kAnyTransactionID)) let resultEvent = try appleEvent.sendEvent(options: [.queueReply], timeout: TimeInterval(kNoTimeOut)) Here is what the event handler looks like in the target application: @objc func handler(event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) { try replyEvent!.sendEvent(options: [.noReply], timeout: TimeInterval(kNoTimeOut)) } I encountered two difficulties using the ‘queueReply’ sending mode: I see the input window for credentials in the case when the event handler app tries to send the response to the sender app. (This is a problem for me since there is no one to enter the password on the side of the handler app. This window for credentials entry is not displayed if the sending is in the “waitForReply” mode) After entering the correct credentials, the sender app receives the error AppleEvents/sandbox: Returning errAEPrivilegeError/-10004 Sender app logs: {test,evnt target=aprl(38/$657070633a2f2f3139322e3136382e302e3131352f6170706c654576656e7448...) {} returnID=27646} 2023-02-20 15:42:24.045320+0200 testevents[41720:2641106] [main] ERROR: AEImpl::~AEImpl fRetainCount not zero (1) {aevt,ansr target=aprl(38/$657070633a2f2f3139322e3136382e302e3131352f6170706c654576656e7448...) {} returnID=27646} 2023-02-20 15:42:29.593044+0200 testevents[41720:2641063] Suite NSCoreSuite, apple event code 0x1061109567x 2023-02-20 15:42:29.595201+0200 testevents[41720:2641063] Suite NSTextSuite, apple event code 0x1061109567x 2023-02-20 15:42:29.840410+0200 testevents[41720:2641063] [main] AppleEvents/sandbox: Returning errAEPrivilegeError/-10004 and denying dispatch of event aevt/ansr from process ‘’/0x0-0x0, pid=0, because it is not entitled to send the AppleEvent to this process. Handler app logs: {test,evnt target=aprl(27/$657070633a2f2f3139322e3136382e302e3131353a35393037362f) {}} {aevt,ansr target=aprl(27/$657070633a2f2f3139322e3136382e302e3131353a35393037362f) {}} 2023-02-20 15:42:29.569897+0200 appleEventHandler[41454:2635163] [main] ERROR: AEImpl::~AEImpl fRetainCount not zero (1) 2023-02-20 15:42:29.576049+0200 appleEventHandler[41454:2640788] [connection] nw_socket_handle_socket_event [C4:1] Socket SO_ERROR [61: Connection refused] 2023-02-20 15:42:29.577080+0200 appleEventHandler[41454:2638578] [connection] nw_connection_get_connected_socket [C4] Client called nw_connection_get_connected_socket on unconnected nw_connection ... In this case, the sender app receives the response but is not handled. Handler code: NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handler), forEventClass: AEEventClass(stringLiteral: “aevt”), andEventID: AEEventID(stringLiteral: “ansr”)) @objc func handler(_ event: NSAppleEventDescriptor?, withReplyEvent: NSAppleEventDescriptor?) throws { print(event?.description) } But this code works correctly with: let target = NSAppleEventDescriptor(bundleIdentifier: “test.com.appleEventHandler”) Logs: {test,evnt target=bund(26/$746573742e636f6d2e6170706c654576656e7448616e646c6572) {} returnID=3183} {aevt,ansr target=appleEventHandler {} returnID=3183} Optional(“&lt;NSAppleEventDescriptor: \‘aevt\’\\‘ansr\’{ }&gt;“) {aevt,ansr target=appleEventHandler {} returnID=3183} Optional(“&lt;NSAppleEventDescriptor: \‘aevt\’\\‘ansr\’{ }&gt;“) Please help me to understand how can I get an async response using the send option “queueReply” by eppc? (“waitForReply” option works correctly with eppc in this code)
Replies
7
Boosts
0
Views
1.3k
Activity
Mar ’23
orderWindows not reliable/changed in Ventura
My application can be controlled by scripts using AppleScript, python (through scripting bridge), or my own internal scripting language in a script thread. I just noticed that scripts that need to know the current front window have stopped working in Ventura. I find the front window as the first relevant window in [NSApp orderedWindows] (in Objective C). I found the problem with Ventura by adding some debugging output as follows: Run a script thread to control my application When a new window is needed, this thread uses performSelectorOnMainThread to create a window and waits for it to appear and to get added to the document. Before returning from main thread selector, the ordered windows are checked and they are correct (the new window is an AncestorController). DEBUG: check window order after creating an AncestorController DEBUG: frontGEDCOMController windows are: ...1 of 2 <NSWindow: 0x123691e20> <AncestorController: 0x600001fc50e0> ...2 of 2 <NSWindow: 0x123641ad0> <IndexController: 0x6000019c0c40> ...current front window is AncestorController Immediately on return to script thread, however, another performSelectorOnMainThread is called to check the order of the windows again and it has changed in an instant to the wrong order (wrong because the AncestorController is still in front). DEBUG: recheck window order after 0.000000 seconds DEBUG: frontGEDCOMController windows are: ...1 of 2 <NSWindow: 0x123641ad0> <IndexController: 0x6000019c0c40> ...2 of 2 <NSWindow: 0x123691e20> <AncestorController: 0x600001fc50e0> ...front window type is IndexController But, if I sleep the thread, the order changes back to correct order in <= 1/30 second DEBUG: recheck window order after 0.033333 seconds DEBUG: frontGEDCOMController windows are: ...1 of 2 <NSWindow: 0x123691e20> <AncestorController: 0x600001fc50e0> ...2 of 2 <NSWindow: 0x123641ad0> <IndexController: 0x6000019c0c40> ... front window type is AncestorController This issue is new to Ventura. For some reason Ventura adds a window to the list in the correct position. It then movies to the wrong possible for a short amount of time before then returning to the correct position. That did not happen in MacOS 12.x or earlier. Now maybe I can find all the places my scripts that need to pause for Ventura to get things right, but it would be better to know why it has happened and then know where I need to insert Ventura hacks? Or is there another way that can reliably get ordered windows in Ventura? Curiously this problem does not occur when scripting by AppleScript. Maybe that is just so slow that pauses happen all the time anyway. I did find an alternative method to get ordered windows introduced in 10.12: enumerateWindowsWithOptions:usingBlock: with option NSWindowListOrderedFrontToBack but it is identical to using orderedWindows (i.e., gets the order wrong for a while).
Replies
0
Boosts
0
Views
1.1k
Activity
Dec ’22
Sending file parameters to a Shortcut on Monterey programmatically?
I'm trying to run Shortcuts programmatically on Monterey. My understanding is that the official API for this is via AppleScript to the Shortcuts Events process. I created a Shortcut that does Quicklook on the passed in file parameter. It works as a Finder action but I can't figure out how to get it to work when running it via AppleScript or Scripting Bridge. If I send a file, alias or POSIX file, I get a generic Shortcuts error 4. If I send a path as a string, it just does a preview of the string passed in, and not the contents of the file the path references. Anyone have any insight on how to get this working?
Replies
0
Boosts
0
Views
957
Activity
Sep ’21