Friday, October 22, 2021

#1 2019-10-11 03:17:26 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 1089

AppleScript App Backgrounder

IMPORTANT NOTE: I just upgraded to Catalina and after modifying a script to run in the background with the script included below, I received the following error:

Not authorized to send Apple events to Finder. (-1743)



I only received this error message with one script but, still, some caution is necessary when using this script under Catalina.

About a third of my regularly-used Applescripts are saved as apps, and I've found some advantage to running a number of them in the background. This can be done by enabling the LSUIElement property list key, which is described by Apple as:

LSUIElement (Boolean - macOS) specifies whether the app runs as an agent app. If this key is set to YES, Launch Services runs the app as an agent app. Agent apps do not appear in the Dock or in the Force Quit window. Although they typically run as background apps, they can come to the foreground to present a user interface if desired. A click on a window belonging to an agent app brings that app forward to handle events.


Normally the value of LSUIElement is modified in a terminal window, but I change it often enough that I wrote the following script, which works as an enable/disable toggle. I've been using this script for some time on AppleScript apps without issue but have never used it with any other app.

Applescript:


--Prompt user for app.
set selectedApp to POSIX path of (choose file of type "com.apple.application-bundle")

--Set variable to name of app.
set AppleScript's text item delimiters to "/"
set appName to text item -2 of selectedApp
set AppleScript's text item delimiters to ""

--Set variable to background status of app.
try
   set backgroundFlag to do shell script "defaults read " & quoted form of selectedApp & "/Contents/Info LSUIElement"
on error
   set backgroundFlag to "NO"
end try

--Set variables to dialog message and background flag.
if backgroundFlag = "YES" then
   set dialogMessage to "Set " & quote & appName & quote & " to run in the foreground."
   set backgroundFlag to "NO"
else
   set dialogMessage to "Set " & quote & appName & quote & " to run in the background."
   set backgroundFlag to "YES"
end if

--Prompt to change background status.
display dialog dialogMessage buttons {"Cancel", "OK"} cancel button 1 default button 2 with title "App Backgrounder"

--Write changes to app.
try
   do shell script "defaults write " & quoted form of selectedApp & "/Contents/Info LSUIElement " & backgroundFlag
on error errorMessage
   display dialog "The following error was reported while setting the background flag: " & return & return & errorMessage buttons {"OK"} cancel button 1 default button 1 with title "App Backgrounder" with icon stop
end try

Last edited by peavine (2019-12-06 08:00:45 am)


2018 Mac mini - macOS Catalina - Script Debugger 8

Offline

 

#2 2019-10-11 04:54:30 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6708

Re: AppleScript App Backgrounder

FYI, in the Resources Tab in a Script Debugger window is a checkbox, Background only, which lets you make the change permanently.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#3 2021-08-14 08:13:24 am

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 1089

Re: AppleScript App Backgrounder

Now that I'm using Script Debugger, I did a little additional research on this topic by setting an AppleScript applet to run in the background with the above script and by doing this with Script Debugger. I noticed two differences:

* The Script Debugger applet reported an error if it contained code that resulted in user interaction (e.g. a display dialog). The other script did not do this.

* The Info-LSUIElement flag was not set by the Script Debugger applet; I guess that's what Shane was referring to when he said that the change was made permanently.

Other than the above, I don't know if there's any reason to prefer one approach over the other.


2018 Mac mini - macOS Catalina - Script Debugger 8

Offline

 

#4 2021-08-14 06:27:59 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6708

Re: AppleScript App Backgrounder

Script Debugger's setting uses the LSBackgroundOnly key, not LSUIElement.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#5 2021-08-14 07:32:24 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 1089

Re: AppleScript App Backgrounder

Thanks Shane.

LSUIElement is defined in post 1, and LSBackgroundOnly is defined as:

LSBackgroundOnly (Boolean - macOS) specifies whether this app runs only in the background. If this key exists and is set to YES, Launch Services runs the app in the background only. You can use this key to create faceless background apps. You should also use this key if your app uses higher-level frameworks that connect to the window server, but are not intended to be visible to users. Background apps must be compiled as Mach-O executables. This option is not available for CFM apps.



The following script returns the background-only and agent-app status of an AppleScript applet selected in a Finder window:

Applescript:

-- Revised 2021.08.18

on main()
   tell application "Finder"
       try
           set selectedApp to selection as alias
           set appName to name of selectedApp
           set appExtension to name extension of selectedApp
       on error
           display alert "An error has occurred" message "Multiple or no files selected" as critical
           error number -128
       end try
   end tell
   set selectedApp to quoted form of POSIX path of selectedApp
   
   if appExtension ≠ "app" then
       display alert "An error has occurred" message "The selected file may not be an app" as critical
       error number -128
   end if
   
   try
       set backgroundApp to do shell script "defaults read " & selectedApp & "/Contents/Info LSBackgroundOnly"
       if backgroundApp = "1" then
           set backgroundApp to "YES"
       else
           set backgroundApp to "NO"
       end if
   on error
       set backgroundApp to "NOT SET"
   end try
   
   try
       set agentApp to do shell script "defaults read " & selectedApp & "/Contents/Info LSUIElement"
   on error
       set agentApp to "NOT SET"
   end try
   
   display alert "The app " & quote & (text 1 thru -5 of appName) & quote message "Background only is " & backgroundApp & linefeed & "Agent app is " & agentApp as informational
end main

main()

Last edited by peavine (2021-08-18 09:32:55 am)


2018 Mac mini - macOS Catalina - Script Debugger 8

Offline

 

#6 2021-08-30 01:49:42 pm

wch1zpink
Member
Registered: 2011-08-20
Posts: 63

Re: AppleScript App Backgrounder

peavine wrote:


Normally the value of LSUIElement is modified in a terminal window, but I change it often enough that I wrote the following script, which works as an enable/disable toggle. I've been using this script for some time on AppleScript apps without issue but have never used it with any other app.

Applescript:


--Prompt user for app.
set selectedApp to POSIX path of (choose file of type "com.apple.application-bundle")

--Set variable to name of app.
set AppleScript's text item delimiters to "/"
set appName to text item -2 of selectedApp
set AppleScript's text item delimiters to ""

--Set variable to background status of app.
try
   set backgroundFlag to do shell script "defaults read " & quoted form of selectedApp & "/Contents/Info LSUIElement"
on error
   set backgroundFlag to "NO"
end try

--Set variables to dialog message and background flag.
if backgroundFlag = "YES" then
   set dialogMessage to "Set " & quote & appName & quote & " to run in the foreground."
   set backgroundFlag to "NO"
else
   set dialogMessage to "Set " & quote & appName & quote & " to run in the background."
   set backgroundFlag to "YES"
end if

--Prompt to change background status.
display dialog dialogMessage buttons {"Cancel", "OK"} cancel button 1 default button 2 with title "App Backgrounder"

--Write changes to app.
try
   do shell script "defaults write " & quoted form of selectedApp & "/Contents/Info LSUIElement " & backgroundFlag
on error errorMessage
   display dialog "The following error was reported while setting the background flag: " & return & return & errorMessage buttons {"OK"} cancel button 1 default button 1 with title "App Backgrounder" with icon stop
end try



@peavine  Your AppleScript code broke some functionality of several of my AppleScript applets using the latest version of macOS Big Sur.

I took the liberty to add some Handlers with short descriptions, adding functionality to your original code.  Now this  AppleScript code works flawlessly for me using the latest version of macOS Big Sur.


Applescript:

--Prompt user for app.
activate
set selectedApp to POSIX path of (choose file of type "com.apple.application-bundle")

--Set variable to name of app.
tell application "System Events" to set appName to name of (selectedApp as POSIX file as alias)

--Set variable to background status of app.
try
   set backgroundFlag to do shell script "defaults read " & quoted form of selectedApp & "/Contents/Info LSUIElement"
on error
   set backgroundFlag to "NO"
end try

--Set variables to dialog message and background flag.
if backgroundFlag = "YES" then
   set dialogMessage to "Set " & quote & appName & quote & " to run in the foreground."
   set backgroundFlag to "NO"
   removeLogEntry(appName)
else
   set dialogMessage to "Set " & quote & appName & quote & " to run in the background."
   set backgroundFlag to "YES"
   logAppSetToRunInBackgroundOnly(appName)
end if

--Prompt to change background status.
activate
display dialog dialogMessage buttons {"Cancel", "OK"} cancel button 1 default button 2 with title "App Backgrounder"
delay 0.1

--Write changes to app.
try
   do shell script "defaults write " & quoted form of selectedApp & "/Contents/Info LSUIElement " & backgroundFlag
   compileAppScript((selectedApp as POSIX file as alias))
on error errorMessage
   activate
   display dialog "The following error was reported while setting the background flag: " & return & return & errorMessage buttons {"OK"} cancel button 1 default button 1 with title "App Backgrounder" with icon stop
end try

-------------------- Handlers --------------------

(* If "Backgrounded_Apps.log" file does not already exist on your Desktop,
It will be automatically created. Every time you set any AppleScript app to
"Background Only Mode", that app will be added to the "Backgrounded_Apps.log"
file. This is an excellent way to keep track of all the AppleScript applications
currently set to "Background Only". *)

on logAppSetToRunInBackgroundOnly(appName)
   set currentDate to (current date) as string
   set theFile to (path to desktop as text) & "Backgrounded_Apps.log"
   set myName to appName
   
   try
       if myName is not in (paragraphs of (read file theFile) as text) then
           set theText to myName & " was set to run in " & quote & "Background Only" & quote & " mode on " & currentDate
           do shell script "echo " & quoted form of theText & " >> " & quoted form of POSIX path of theFile
       end if
   on error errMsg number errNum
       set theText to myName & " was set to run in " & quote & "Background Only" & quote & " mode on " & currentDate
       do shell script "echo " & quoted form of theText & " >> " & quoted form of POSIX path of theFile
   end try
end logAppSetToRunInBackgroundOnly

(* Every time you set an AppleScript application back to "Foreground Mode",
that app will be removed from the "Backgrounded_Apps.log" file. *)

on removeLogEntry(appName)
   set theFile to (path to desktop as text) & "Backgrounded_Apps.log"
   set myName to appName
   -- Using "-pboard ruler" preserves normal clipboard's current content
   do shell script "cat " & quoted form of POSIX path of theFile & "| egrep -v " & ¬
       "'" & myName & "' | pbcopy -pboard ruler ; pbpaste -pboard ruler > " & quoted form of POSIX path of theFile
end removeLogEntry

(* This will recompile and save any AppleScript app whenever its
"Background or Foreground Mode" has been changed. For me, if I
did not run the code in this handler, some of my AppleScript
apps lost functionality *)

to compileAppScript(chosenApp)
   try
       tell application "Script Debugger"
           launch
           set theApp to open chosenApp
           delay 0.1
           set succesfulCompile to compile theApp with showing errors
           delay 0.1
           close theApp saving yes
       end tell
   end try
   return succesfulCompile
end compileAppScript

Offline

 

#7 2021-08-30 02:38:57 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 1089

Re: AppleScript App Backgrounder

wch1zpink. Thanks for looking at my script and for the suggested revisions. Maintaining a log of AppleScript applets that have been set to run in the background is a nice enhancement.

I was interested by your following comment, because I had previously found that whenever an AppleScript applet wouldn't run after applying my script, I could open and then immediately save the AppleScript applet in Script Debugger, which seemed to fix the problem. Your script, of course, automates this process.

This will recompile and save any AppleScript app whenever its "Background or Foreground Mode" as been changed. For me, if I did not run the code in this handler, some of my AppleScript apps lost functionality



When this became an issue, I seem to recall that my script jumbled the AppleScript applet's info.plist file and that Script Debugger unjumbled it. I have little knowledge of plist files and don't know if that was the reason my script breaks some AppleScript applets.

I had hoped Shane would consider adding this functionality to Script Debugger, which would be ideal, but that appears unlikely:

https://forum.latenightsw.com/t/setting … -only/3264

Last edited by peavine (2021-08-30 05:02:20 pm)


2018 Mac mini - macOS Catalina - Script Debugger 8

Offline

 

#8 2021-08-30 05:29:55 pm

wch1zpink
Member
Registered: 2011-08-20
Posts: 63

Re: AppleScript App Backgrounder

peavine wrote:

wch1zpink. Thanks for looking at my script and for the suggested revisions. Maintaining a log of AppleScript applets that have been set to run in the background is a nice enhancement.



peavine, I already had  something very similar to what you have, with a few differences.  My version has an on open Handler also, allowing me to either launch the app directly or handle/process multiple dropped items dragged onto the applet’s icon.  Because of the amount of code with the additional “open handler”, my version does not have the ”Logging Handlers” which I added to your code for you.  My version has the ”Logging Handlers” in a separate Library script, which I call on via the “load script” command.

My version of the App Backgrounder Droplet code —> https://pastebin.com/SNFNnTaX
The Logging Library Script —> https://pastebin.com/gkVXMM6t

Last edited by wch1zpink (2021-08-30 05:30:16 pm)

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)