[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