Reputation: 29421
Our product allows updates to be installed via an MSI installer. An update consists of several files which need to be copied to disk, and the addition of database entries which the installer adds by running several SQL scripts.
Updates can be (and commonly are) installed while the main executable is open. Because of this, I need a way of preventing access to a certain database-intensive feature while the upgrade is in progress.
My current thoughts:
Meanwhile, the application (written in C#) queries for the presence of the registry key, displaying an error dialog if it is set.
Is this reliable? I'm concerned about what happens if the user kills the installer via task manager, then the registry key will never be deleted and the user will be permanently locked out of the feature. Also not sure about any race conditions that the above solution could lead to.
Any suggestions about whether this approach is feasible, or a better approach?
Upvotes: 0
Views: 224
Reputation: 55581
Windows Installer already implements a Mutex to indicate that an installation is in progress. Just code your database intensive code to check for that mutex and no-op while it's present. Nothing additional needs to be done.
(Note: using this will stop your processing any time MSI is installing a product which is probably not a bad idea anyways. If you want a unique mutex, it's trivial to write a custom action. )
Update by @LeopardSkinPillBoxHat
The above answer did what I needed. This is the code I ended up using:
static void Main(string[] args)
{
try
{
Mutex mutex = Mutex.OpenExisting(@"Global\_MSIExecute");
if (!mutex.WaitOne(TimeSpan.FromSeconds(5), false))
{
Console.WriteLine("Installation in progress!");
return;
}
}
catch (AbandonedMutexException)
{
Console.WriteLine("Mutex was abandoned");
}
catch (WaitHandleCannotBeOpenedException)
{
Console.WriteLine("MSI installer not running");
}
// Perform operation here
}
Upvotes: 2
Reputation: 15816
ALTER DATABASE <name> SINGLE_USER
As described here will break all other connections and allow you to proceed with the update.
Upvotes: 1
Reputation: 7618
Would using a named Mutex be reasonable here? Require that the intensive tasks and the updater first acquire the mutex before executing.
EDIT: I lied about wrapping the mutex in a using
will protect you from task manager shutdowns. Makes sense, you wouldn't expect finally
blocks to execute either. What you'll end up with is an AbandonedMutex, which is discussed in the msdn article I linked.
Also saw recently a useful little article about using a Mutex to prevent multiple instances of the same program from executing.
Upvotes: 2