How Do I Get Recent Files of All Apps?

And with AppKit's help we can simplify it a bit, and speed it up more than somewhat:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == %@" argumentArray:{0}
set foregroundBundleIDs to ((theApps's filteredArrayUsingPredicate:thePred)'s valueForKey:"bundleIdentifier") as list
2 Likes

Thanks. I was thinking about NSWorkspace’s runningApplications but wasn’t aware of
NSApplicationActivationPolicy.

Extending that slightly, and a bit off topic, but we can produce a potentially useful script that separates running bundle IDs according to background, menubar or foreground that belong to 3rd party processes (this has already helped me troubleshoot a problem for someone else):

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set nonAppleForeground to {}
set nonAppleMenubar to {}
set nonAppleBackground to {}

on excludeAppleIDs:ids
	set returnList to {}
	repeat with ident in ids
		if ident does not contain "com.apple" and ident does not contain missing value then
			set end of returnList to ident as text
		end if
	end repeat
	return returnList
end excludeAppleIDs:

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()

repeat with i from 0 to 2
	set thePred to (current application's NSPredicate's predicateWithFormat:"activationPolicy == %@" argumentArray:{i})
	if i is equal to 0 then
		set nonAppleForeground to (my excludeAppleIDs:(((theApps's filteredArrayUsingPredicate:thePred)'s valueForKey:"bundleIdentifier") as list))
	else if i is equal to 1 then
		set nonAppleMenubar to (my excludeAppleIDs:(((theApps's filteredArrayUsingPredicate:thePred)'s valueForKey:"bundleIdentifier") as list))
	else
		set nonAppleBackground to (my excludeAppleIDs:(((theApps's filteredArrayUsingPredicate:thePred)'s valueForKey:"bundleIdentifier") as list))
	end if
end repeat



You can do that in the predicate. You can also use it to skip processes that don’t have a bundle ID:

	set thePred to (current application's NSPredicate's predicateWithFormat:"activationPolicy == %@ AND bundleIdentifier != %@ AND NOT bundleIdentifier BEGINSWITH %@" argumentArray:{i, missing value, "com.apple"})
3 Likes

And for a bit more code parsimony, you could set the result variables by list:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set theBundleIDs to current application's NSMutableArray's new()

repeat with i from 0 to 2
	set thePred to (current application's NSPredicate's predicateWithFormat:"activationPolicy == %@ AND NOT (bundleIdentifier == NIL OR bundleIdentifier BEGINSWITH 'com.apple')" argumentArray:{i})
	tell theBundleIDs to addObject:((theApps's filteredArrayUsingPredicate:thePred)'s valueForKey:"bundleIdentifier")
end repeat

set {nonAppleForeground, nonAppleMenubar, nonAppleBackground} to theBundleIDs as list
2 Likes

Hi Shane,

Is it possible to set the predicate to filter apps that are scriptable?
For now, I’m using this (improved by your activationPolicy snippet):

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0"
set appsURL to ((theApps's filteredArrayUsingPredicate:thePred)'s valueForKey:"bundleURL")

set scriptableApps to current application's NSMutableArray's new()
repeat with anURL in appsURL
	set {hasResult, theResult} to (anURL's getResourceValue:(reference) forKey:(current application's NSURLApplicationIsScriptableKey) |error|:(missing value))
	if theResult as boolean then
		set aBundle to ((current application's NSBundle's bundleWithURL:anURL)'s bundleIdentifier())
		(scriptableApps's addObject:aBundle)
	end if
end repeat
scriptableApps as list

Hey, that’s clever! I’d never have thought of using NSMutableArray and lists together like that.
Thanks Nigel!

I think that’s as good as it gets.

Very cool script, Nigel! :+1:

Plus, I learned a new word: parsimony

Much nicer, elegant way of saying someone/something is “cheap” or “stingy”.

So now, instead of saying “compact script”, we can say “parsimonious script” LOL
Why use a 7-letter word, when we can us a 12-letter word? LOL

But thanks! I do like learning a new word every day.