[Sparkle] How Sparkle Handles Background Helper Apps [solved]
Jerry Krinock
jerry at sheepsystems.com
Tue Jul 17 20:50:57 PDT 2007
As indicated, this problem is solved, but since Sparkle is a little
shy on documentation, and since I needed to write all this down to
convince myself that it was going to work anyhow, I thought I'd enter
it into the archives for others who may come to this situation....
My application Bookdog has in its Contents/Resources a background
helper application, "Bookwatchdog", which may be running continuously
depending on Preferences settings. However, Bookdog 4.2 running
with, say, Bookwatchdog 3.2 might not be a happy combination and
certainly has never been tested. Therefore, I require that
Bookwatchdog be quit and trashed along with the main application when
updating. This seems obvious but, when doing a manual drag-and-drop
upgrade, the Finder will not allow a package containing a running
process to be trashed. So, I had provided in the dmg a
doubleclickable script which would quit Bookwatchdog for users that
ran into this problem. (Another thing I did for awhile was to have
Apple Installer run this script, but let's not go there.)
I was expecting to have to hack Sparkle to get similar behavior, but
to my surprise it seemed to "just work". What happens is that the
NSFileManager methods used by Sparkle to trash the old app package
don't care about the running helper. The helper executable, already
loaded into memory and running, is happily moved to the trash.
However, that still leaves an old helper running, so we're not done
yet. For purposes of updating preferences if needed, my app stores
the previously-run version in its Preferences. (To my surprise, I
was actually smart enough to do this even in version 1.0.) I imagine
most of you do this also. Furthermore, I had previously implemented
a little launch-time code which would quit Bookwatchdog whenever an
update was detected. This runs before the code which will re-launch
(the new) Bookwatchdog if it is needed, so, voila, we're done!
However, before I recalled this and convinced myself that it was
good, I experimented with another approach today which seemed on the
surface to be more bulletproof. The idea was to get the
CFBundleShortVersionString of the running Bookwatchdog, compare it
with the CFBundleShortVersionString of the Bookwatchdog in the -
mainBundle, and quit Bookwatchdog if not equal. This approach did
not work.
Here's why. I used the following algorithm to find the path of the
running Bookwatchdog...
1. Iterate through running processes using GetNextProcess() until
a process with name matching my helper is found.
2. Get the process serial number (psn) from the process ID (pid)
using GetProcessForPID()
3. Get the path of this process using GetProcessInformation(),
and then the usual Carbon
fire-drill: FSpMakeFSRef(), FSRefMakePath(), [NSString
stringWithCString].
However, the path that I get from GetProcessInformation() is the path
of the helper when it was launched, and before it was moved to the
trash. So it then gets the CFBundleShortVersionString of the new
app, failing to detect the update. I suppose the OS is returning the
"launch path" that was the first argument of the unix command line
that launched it. Same problem can be seen if I run the unix ps
command and grep out Bookwatchdog after it has been moved to the
trash; it still shows the old path.
More information about the Sparkle
mailing list