Recently I was creating installer for application that is suppose to be updated regulary. Also cab installer for this application used setup.dll to perform custom actions during install/uninstall.
Since cab installer doesn’t have “update” feature installing update is done as a sequence: uninstall_old > install_new. Calls to setup.dll will be as follows:
- Install_Init() from new setup.dll is called with fFirstCall=true and fPreviouslyInstalled=true.
- Old installation is removed. This leads to calls to Uninstall_Init() and Uninstall_Exist() from old setup.dll (which is stored in \windows\AppMgr).
- Install_Init() from new setup dll is called with fFirstCall=false and fPreviouslyInstalled=false.
- New files are extracted by cab installer.
- Install_Exist() is called.
To control updating process I needed to use some kind of a marker that will be available at all of those steps.
Originally I tried to use named Mutex (mainly because it is an in-memory object), but for some reason it didn’t work as expected. So I considered key in registry and a file. Creating/removing file just to use it as a marker is not very good idea and my final solution was to use a key in registry:
#include "windows.h"
#include <string.h>
///////////////////////////////////////////////////////////
// Methods to work with marker.
void SetInstallingStartFlag() {
HKEY hKey = NULL;
DWORD dwDisposition;
if (::RegCreateKeyEx(HKEY_CURRENT_USER, _T("\\SOFTWARE\\MySoftwareInstall"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) {
::RegCloseKey(hKey);
}
}
void RemoveInstallingStartFlag() {
HKEY hKey = NULL;
if (::RegOpenKeyEx(HKEY_CURRENT_USER, _T(""), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
::RegDeleteKey(hKey, _T("\\SOFTWARE\\MySoftwareInstall"));
::RegCloseKey(hKey);
}
}
BOOL OpenFlagKey() {
BOOL bOpened = FALSE;
HKEY hKey = NULL;
if (::RegOpenKeyEx(HKEY_CURRENT_USER, _T("\\SOFTWARE\\MySoftwareInstall"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
bOpened = TRUE;
::RegCloseKey(hKey);
}
return bOpened;
}
BOOL IsRemovingDuringUpdate() {
return OpenFlagKey();
}
BOOL IsInstallingDuringUpdate() {
return (OpenFlagKey() == FALSE);
}