how to cleanup launchctl when removing app - macos

I writing an app for Mac, one of it's components is a launchctl agent that runs in background.
As mac apps are removed by dragging to trash (I can understand this logic but takes getting used to after years of windows dev'ing), I'm wondering is there anything I can do to cleanup after myself when the user removes the app?
specifically the running background process and its .plist file.
Edit:
After some more thinking about the issue, I have an idea to put a listener on the background process file, get notified if it's deleted, then remove itself from launchctl, delete plist and kill itself. can this work?

Related

Erlang wxWidgets app - Closing the beam.smp file once app finished

got a weird question which I haven't been able to find an answer to online so I'm trying my luck here.
I have a normal erlang application using wxWidgets, once I try to shut down my application I get the event that the wxServer has indeed entered the event which is connected to the window closing, I get a message that it is in the process of exiting, and my window does indeed close, but as shown in the picture below, the beam.smp on my toolbar doesn't close at all, I have to manually force the closing of the beam.smp file which sends a SIGTERM to the erlang terminal which also shuts down my erlang VM (which I have to reboot it later).
long story short, what am I missing on my close window event so that everything shuts down nicely without it crashing my erlang VM? I was able to read that wxWidgets behaves differently on macOS but I haven't been able to find how to correctly close the application.
handle_event(#wx{event = #wxClose{}},State = #state{frame = Frame,panel = Panel}) ->
io:format("Exiting~n"),
wxFrame:close(Frame),
wxFrame:destroy(Frame),
wx:destroy(),
{stop,normal,State};
You can close the emulator from code with init:stop/0,1
Also, if your application is started as permanent, it should suffice with terminating that application. Check the behaviour in erlang:application

applicationShouldTerminate: not called when system restarts

I have to run some code when the app is about to terminate. applicationShouldTerminate: runs when quit is selected from the menu or when I press Cmd Q but not when I restart the mac.
Is there a way to force applicationShouldTerminate when a user tries to restart the mac? Or is it another function being called in this scenario?
Your app might have Sudden Termination enabled.
macOS 10.6 and later includes a mechanism that allows the system to log out or shut down more quickly by, whenever possible, killing applications instead of requesting that they quit themselves.
...
Debugging tip
You can determine the value of the sudden termination using the following LLDB command.
print (long)[[NSClassFromString(#"NSProcessInfo") processInfo] _suddenTerminationDisablingCount]

How does Steam prompt me to delete game data when I delete the app?

I recently tried delete Steam.app from Mac OS X 10.10.5. As soon as I hit Command-Backspace to remove the application, this dialog appeared:
The text reads:
Steam still has some game content stored at /Users/apaidnerd/Application Support/Steam/SteamApps. Do you want to delete the game content as well?
[Leave files] [Reveal in Finder] [Delete files]
How did the Steam application cause this to happen? If I'm developing an app for Mac OS X, where is this documented?
You were close. It looks to me like the launch agent "com.valvesoftware.steamclean" is responsible for this. Unloading the "com.valvesoftware.steam.ipctool" agent/service may effectively disable the other one.
The steamclean agent's description plist file is in ~/Library/LaunchAgents. It doesn't poll. It has a WatchPaths key, which asks launchd to run it when that path changes. launchd uses file system notification techniques to monitor that, which also don't rely on polling.
When that happens, the agent runs the program ~/Library/Application Support/Steam/SteamApps/steamclean, which is not in the Steam.app bundle. It couldn't be, because the app bundle has been moved or renamed, so launchd would not be able to find the program for the agent. steamclean is what shows the dialog. You can confirm this by reproducing the dialog and leaving it open. Then, use Activity Monitor to list the processes and filter for "steam".
Figured it out. Steam has a launchctl agent that runs (com.valvesoftware.steam.ipctool) out of the /Applications/Steam.app/ directory. If I stop the daemon and remove the Steam.app, no dialog appears.
It must poll to see if its executable path still exists and prompts the user if goes missing. Also, the inactive-looking title bar implies that this dialog is indeed coming from some sort of background process.

OS X LaunchAgent - Run when desktop ready?

I've created a bash script which does some complex stuff, including some bits of Applescript which involves clicking pop ups, its to run on every new account created on the machine to set up some browser extensions for users (Adblock etc)
The script runs when manually invoked just fine, but when put as a LaunchAgent is erratic at best. It seems to run whilst the create account login/password screen is up - it opens a welcome PDF for a start off and sometimes when you log in, preview is already open without the file.
Othertimes you log in and nothing happens for a good 50 seconds. Occasionally its behaviour is erratic too.
The script needs to run as a launchagent as it runs once per new account - the script actually deletes the launchagent plist at the end so it can't run again. Is there anyway to delay the running of the script to have it start once the desktop is fully loaded? Perhaps once the dock has appeared. I'm going to assume its trying to run too early, it can't open Preview or Safari, it tries to delete the plist which is in use and then just ends up in a confused loop. Obviously not the cleanest way to run.

Unloading my plugin from another process

I'm toying with adding an NSDockTilePlugIn to my application, but I've come across some strange behavior -- understandable behavior, but I'd like to see if there is a way around it.
When I run my app from the dmg or keep the (dmg version of the) app in the Dock, the Dock loads my .docktileplugin bundle.
When the application quits, the plugin receives a setDockTile: message with a nil NSDockTile * (as per the documentation). However, the plugin keeps running, and I cannot eject (unmount, detach) the dmg unless I kill the Dock (I suppose logging out would work too).
I've tried sending a Notification through the NSDistributedNotificaitonCenter (from a non-dmg version of the app) to tell it to unload, but the Console tells me that now I have two of the same docktileplugin loaded, and it is undefined which one will execute.
And even though [[NSBundle bundleWithPath:...] unload] returns YES, I still cannot eject the dmg.

Resources