0

I have a code:

func openGetInfoWnd(for urls: [URL]) {
    let pBoard = NSPasteboard(name: NSPasteboard.Name(rawValue: "pasteBoard_\(UUID().uuidString )") )
    
    pBoard.writeObjects(urls as [NSPasteboardWriting])
    
    NSPerformService("Finder/Show Info", pBoard)
}

this code opens multiple windows of Finder's "Get Info"

like it displays on Cmd + I hotkey

How can I open single one window ("Show Inspector" / "Get Info" / "Multiple Item Info") for multiple local urls?

Like it displayed on Cmd + Option + I press in Finder

enter image description here

PS: code: NSPerformService("Finder/Show Inspector", pBoard) ofc does not work :)

Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101

2 Answers2

2

Tried many ways, you are right, NSPerformService is very limited, and cannot achieve it. And I also tried Apple Script's approach:

tell application "Finder" to open information window of file aFile

But that only works for the single file and there is no open "multiple information window" thing in Finder.

Luckily, your keyboard shortcuts remind me that I can simulate the file selection and keyboard keydown events.

So I believe below apple script can help you:

set fileList to {POSIX file "/Users/0x67/Downloads/new.html", POSIX file "/Users/0x67/Pictures/tt/00003-771884301.png"}

tell application "Finder"
    activate
    set selection to fileList
    tell application "System Events"
        keystroke "i" using {command down, option down}
    end tell
end tell

enter image description here

I think you can call this create this apple script in Swift and call it.

Here is a useful link to call it in swift:

kakaiikaka
  • 3,530
  • 13
  • 19
  • tried to call this script on my PC with correct local paths and got an error: `NSAppleScriptErrorMessage:Finder got an error: Application isn’t running.; NSAppleScriptErrorRange:NSRange: {240, 8}; NSAppleScriptErrorBriefMessage:Application isn’t running.; NSAppleScriptErrorNumber:-600; NSAppleScriptErrorAppName:Finder;` – Andrew_STOP_RU_WAR_IN_UA May 08 '23 at 14:55
  • same script can be executed from "Script editor" without any issues, but from code this errod displayed – Andrew_STOP_RU_WAR_IN_UA May 08 '23 at 15:18
2

NSAppleScriptErrorNumber: -600 is a sandbox issue, to fix it (tested in Xcode 14.3):

  1. Go to [Your Project] > [Your Target] > Signing & Capabilities.
  2. Delete App Sandbox.
  3. Under Hardened Runtime (add the capability first by clicking + Capability if necessary), check "Apple Events".
  4. Add NSAppleEventsUsageDescription to your Info.plist.

Using @kakaiikaka's answer,

func openGetInfoWnd(for urls: [URL]) {
    let fileList = urls.map { "POSIX file \"\($0.absoluteString)\"" }
    let source = """
set fileList to {\(fileList.joined(separator: ", "))}
tell application "Finder"
    activate
    set selection to fileList
    tell application "System Events"
        keystroke "i" using {command down, option down}
    end tell
end tell
"""
    let appleScript = NSAppleScript(source: source)!
    var error: NSDictionary?
    appleScript.executeAndReturnError(&error)
    
    // ...
}

Rebuild your app (clean build + run) and it should now ask for permissions to send keystrokes to Finder. You'll likely see these pop-ups:

  • Asking for permission to access the directories (the urls with which the function is invoked).
  • Asking for permission to control "Finder" and "System Events" (separate pop-ups with the message you specified for the key NSAppleEventsUsageDescription).
  • Asking for Accessibility Access (you'll have to go to System Settings > Privacy & Security > Accessibility to grant access).

Now everything should work! :)

P.S. If you get a message saying "This method should not be called on the main thread as it may lead to UI unresponsiveness.", just do:

DispatchQueue(label: "AppleScript").async {
    // execute the applescript here instead...
}

(you can also set qos = .background if you want, but either way should work)

Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
AgentBilly
  • 756
  • 5
  • 20
  • 1
    thanks, I believe we did it together! – kakaiikaka May 08 '23 at 20:40
  • @kakaiikaka yay! thanks to you! ;) – AgentBilly May 08 '23 at 20:44
  • Xcode Version 14.3 (14E222b) - there is no capability Apple Events. | NSAppleEventsUsageDescription - already in plist | also there is no `DispatchQueue(name:) `, but there is `DispatchQueue(label: )` (I have fixed your answer at this point). Are you using some old XCode? – Andrew_STOP_RU_WAR_IN_UA May 09 '23 at 00:38
  • The capability you are looking for is "Hardened Runtime" and there is an option called "Apple Events" under that. Sorry for the confusion on `DispatchQueue(label:)`, it was a typo. – AgentBilly May 09 '23 at 04:05
  • 1
    Note: if the inspector window is open then Command-Option-i will close it. – Willeke May 09 '23 at 20:15