Application Updater Block (UAB) and MSI install as "Everyone" does not update.

Topics: Updater Application Block
Apr 26, 2007 at 3:54 PM
Context: UAB 2.0, Visual Studio 2003/.NET 1.1., Manual In-Proc.
I've been struggling to figure out why the UAB does not correctly copy files once downloaded. I'm getting the UAB to spawn PostApplicationExitActivationProcess.exe to perform the copy once the process has exited. Up until yesterday, the fact that the UAB did not copy files seemed to occur randomly. Today, I realized that the UAB does copy files when the application is installed under "Just me" and does NOT copy files when the application installed under "Everyone".

I was wondering if anyone has encountered this and worked around it; or, if possibly, someone might have a clue what a workaround may be?

I'm currently in the process of finding out what is different between installing under "Just me" and "Everyone"; but if someone can offer info that would mean avoiding this tiresome process I would be most appreciative.
May 1, 2007 at 4:54 PM
After quite a bit of research I've tracked down the source of the issue (I'm not clear why installing as "Everyone" or "Just Me" affects it...).

The manifest I'm using is typical in-process; I have two tasks: WaitForApplicationExitProcessor and ApplicationDeployProcessor. It would seem that under certain conditions, the application causing the UAB to spawn PostApplicationExitActivationProcess.exe exits before PostApplicationExitActivationProcess calls Process.GetProcessById, causing an ApplicationException. Unfortunately the code in PostApplicationExitActivationProcess.cs simply returns from Main if GetProcessById causing the next task (ApplicationDeployProcessor) to never get executed.

Clearly there is a race condition that hasn't been accounted for. This is very disconcerting because theoretically another application could get executed and have the same process ID by the time GetProcessId is called--causing the activation process or wait on the wrong application. I'm hoping that the UAB team can offer an official solution, or validate the following workaround (which assumes recycling the process ID in the amount of time applicable approaches impossible--i.e. <~4294967291 processes would need to be created before that process ID would be recycled):
Change existing code in PostApplicationExitActivationProcess.cs from:
Mutex waitMutex = new Mutex( true, String.Format( CultureInfo.InvariantCulture,
"WaitApplication_{0}", applicationId ) );

waitMutex.WaitOne();

try
{
processToWait = Process.GetProcessById( pid );
}
catch
{
return;
}

processToWait.WaitForExit();

// This will get the updater and perform all the pending updates automatically
ApplicationUpdaterManager updater = ApplicationUpdaterManager.GetUpdater(applicationId);
updater.ResumePendingUpdates();

waitMutex.ReleaseMutex();

To:
Mutex waitMutex = new Mutex( true, String.Format( CultureInfo.InvariantCulture,
"WaitApplication_{0}", applicationId ) );

try
{
waitMutex.WaitOne();

try
{
Process processToWait = Process.GetProcessById( pid );

processToWait.WaitForExit();
}
catch(ArgumentException /argumentException/)
{
Logger.LogWarning("Application already exited, resuming pending updates.");
}
catch(Exception exception)
{
Logger.LogException(exception);
return;
}

// This will get the updater and perform all the pending updates automatically
ApplicationUpdaterManager updater = ApplicationUpdaterManager.GetUpdater(applicationId);
updater.ResumePendingUpdates();
}
finally
{
waitMutex.ReleaseMutex();
}