How to Run Applescript without the Dock Icon

I have an AppleScript that I run to do a shutdown. It first clears a few menus and the history of the clipboard app that I use, then counts down three seconds and performs the shutdown. Works great. Nothing I couldn’t do manually, but seeing how it was one of the first scripts that I created when starting with AppleScript, I like to watch it run.

So here’s my question. When the script runs, its icon shows up in the Dock. I’ve read a number of posts that talk about modifying the scripts plist, but the “how” seems to change depending on the macOS. I’m on Monterey 12.7.

Any ideas?

The macOS version is irrelevant. But It’s mandatory that the script is saved as application.

  • Select the application, right-click and choose Show Package Contents

  • Open Info.plist in the folder Contents with TextEdit or another text editor

  • Insert these two lines right before the last </dict> line

    <key>LSBackgroundOnly</key>
    <true/>
    
  • Save the file and quit the text editor.

Now the icon won’t appear in the dock anymore.

1 Like

Thanks, I’ll keep your instructions for use in the future. But, with a bit more searching I found a post by peavine on Late Night Software’s site (Setting an applet to background only - Feature Requests - Late Night Software Ltd.) that addressed this via a feature in Script Debugger: Script Debugger 8 has a “Bundle and Export Settings” option to set an applet to background only. In a thread in MacScripter, Shane said that this option works by enabling the LSBackgroundOnly key.

Opened the script, dropped down the File menu, selected Bundle and Export Settings, clicked the box “Applet is background only”, saved it as an "Application (Apple) . . . and it worked. No Dock icon to be seen!

I know this feature in ScriptDebugger. But you didn’t mention SD in the question.

1 Like

Using LSBackgroundOnly is definitely one option. However, using this method will also hide any pop up dialog boxes which may be in the applet’s code.

Using LSUIElement instead, will also hide the icon from appearing in the dock while allowing any pop-up dialogues to become visible.

<key>LSUIElement</key>
<true/>

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.

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. The Dock and loginwindow are two apps that run as agent apps.

2 Likes

Thank you for that explanation. My goal when I joined here was to learn about AppleScript. It’s a steep learning curve, but responses such as yours certainly make that curve a bit more manageable. Thank you!

If you choose the LSUIElement, the application will not be listed in the “Force Quit” Apple menu bar command. This would force you to have to use the Activity Monitor.app to quit the app.

However, this following code is a quick alternative to being able to force quit the “backgrounded” application.

activate
set theApp to text returned of (display dialog ¬
	"Enter All or Part of Application Name Without Extension" default answer ¬
	"Some App" buttons {"Cancel", "OK"} default button 2 ¬
	with title "Kill Backgrounded App" cancel button 1)

tell application "System Events"
	set theProcess to processes whose name contains theApp
	if (count of theProcess) = 1 then
		set thePID to unix id of theProcess's item 1
		tell current application to (do shell script "kill " & thePID)
	else
		return
	end if
end tell
1 Like

I add this code at the bottom of the script of any app I need to keep open:

do shell script “defaults write /path/to/the/Script.app/Contents/Info.plist LSUIElement -bool yes”

and on the 2nd launch, the icon disappear for good from the doc.

That approach is interesting, but, once the “defaults write /path/to/the/Script.app/Contents/Info.plist LSUIElement -bool yes” is executed the first time, doesn’t it become a redundant part of the script?

Yes it does. But such a small line doesnt make any negative effect at all. Just keep to set the -bool yes. The plus side is also that if you make any change to the script, dont have to bother with the doc icon again and again.

Sometime if the script require to bypass a few security check I also insert a codesign code such:

do shell script “xattr -cr /Users/gc/Documents/˜MyScript/˜Internet/DNS/Menu-Bar_v” & my HD() & “.app && codesign --force --deep --sign - /Users/gc/Documents/˜MyScript/˜Internet/DNS/Menu-Bar_v” & my HD() & “.app”

This solve me many bollox from Mojave on.

1 Like

What does this bit return?

My first question would be to ask for an explanation of what the entire below does?

do shell script “xattr -cr /Users/gc/Documents/˜MyScript/˜Internet/DNS/Menu-Bar_v” & my HD() & “.app && codesign --force --deep --sign - /Users/gc/Documents/˜MyScript/˜Internet/DNS/Menu-Bar_v” & my HD() & “.app”

This is a Menu Bar app which loads on boot. As I use both Mojave and Big Sur and the script are in a shared folder, I need some tweak to let it work on both system.

my HD() is just a function that add the version number to the name of the app according to which OS I am on: Menu-Bar_vx.

Simply let the app to de-quarantine (xattr -cr) and codesign (codesign) itself.