This website uses cookies. By clicking Accept, you consent to the use of cookies. Click Here to learn more about how we use cookies.
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
- Revenera Community
- :
- InstallShield
- :
- InstallShield Forum
- :
- Re: How to remove registry entries conditionally
Subscribe
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Subscribe
- Mute
- Printer Friendly Page
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jan 12, 2010
05:22 AM
How to remove registry entries conditionally
Hi,
I am working on a Basic MSI project and I need to remove some registry entries at installation/deinstallation only if some conditions are fulfilled.
I know I can use the Registry and the RemoveRegistry tables to remove these registry entries, but I need to remove them only if some MSI conditions are fulfilled, and I cannot specify some conditions in these table.
What would be a clever way to do that?
Any suggestion?
Regards
I am working on a Basic MSI project and I need to remove some registry entries at installation/deinstallation only if some conditions are fulfilled.
I know I can use the Registry and the RemoveRegistry tables to remove these registry entries, but I need to remove them only if some MSI conditions are fulfilled, and I cannot specify some conditions in these table.
What would be a clever way to do that?
Any suggestion?
Regards
(11) Replies
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jan 12, 2010
08:13 AM
Hi,
This registry entries are installed by your MSI package?
If not, maybe must write a Custom Action to do this.
Regards,
Kevin
This registry entries are installed by your MSI package?
If not, maybe must write a Custom Action to do this.
Regards,
Kevin
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jan 13, 2010
01:44 PM
Hi,
I have finally gone for an extra table in my Basic MSI project.
It is called RemoveRegistryConditional and contains the following columns:
Then I implemented an InstallScript custom action that iterates through the RemoveRegistryConditional table, checks the condition of each entry.
If the condition evaluates to MSICONDITION_TRUE, then it inserts the corresponding entry in either the Registry table and/or in the RemoveRegistry table, depending on the InstallMode value.
It works quite well, and it is rollbackable if the installation fails, as it relies on the existing RemoveRegistryValues to actually delete the registry entries.
I have finally gone for an extra table in my Basic MSI project.
It is called RemoveRegistryConditional and contains the following columns:
- RemoveRegistry: The key for this table.
- Root: The predefined root key for the registry value.
- Key: The localizable key for the registry value.
- Name: The localizable registry value name.
- Component_: External key into the first column of the Component table referencing the component that controls the deletion of the registry value.
- InstallMode: Same as the InstallMode column of the RemoveFile table. This allows to remove registry entries either when a component is installed or deinstalled.
- Condition: A condition formatted as MSI condition.
Then I implemented an InstallScript custom action that iterates through the RemoveRegistryConditional table, checks the condition of each entry.
If the condition evaluates to MSICONDITION_TRUE, then it inserts the corresponding entry in either the Registry table and/or in the RemoveRegistry table, depending on the InstallMode value.
It works quite well, and it is rollbackable if the installation fails, as it relies on the existing RemoveRegistryValues to actually delete the registry entries.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 20, 2010
03:11 PM
Reureu,
The concept works well on XP as it allows to update the .msi database.
However I failed to do the same thing on Vista/Windows7 as the .msi database is read-only.
Do I miss something and there is a way to make the database writable?
Thanks,
IK
The concept works well on XP as it allows to update the .msi database.
However I failed to do the same thing on Vista/Windows7 as the .msi database is read-only.
Do I miss something and there is a way to make the database writable?
Thanks,
IK
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 21, 2010
12:13 AM
You don't actually modify the MSI database permanently, as it is impossible.
You can use the following InstallScript code to modify your MSI database temporarily:
And make sure this code is scheduled for immediate execution, somewhere between InstallInitialize and RemoveRegistryValues.
I hope that helps.
You can use the following InstallScript code to modify your MSI database temporarily:
/**
* This function temporarily inserts an entry in the RemoveRegistry table.
@ param hMsi: handle to the installer
@ param szRegistry: Primary key, non-localized token
@ param iRoot: The predefined root key for the registry value, one of rrkEnum
@ param szKey: The key for the registry value
@ param szName: The registry value name
@ param szComponent: Foreign key into the Component table referencing component that controls the deletion of the registry value
@ returns: -ERROR_SUCCESS if everything went smoothly
-Other error codes if any error occured when processing the MSI tables.
*/
function INT addItemToRemoveRegistryTable( hMsi, szRegistry, iRoot, szKey, szName, szComponent )
HWND hDB;
HWND hView;
HWND hRecord;
NUMBER nTempResult;
begin
// Open the MSI database
hDB = MsiGetActiveDatabase(hMsi);
if( hDB = NULL ) then
return ERROR_INSTALL_FAILURE;
endif;
// Open a view into RemoveRegistry table
nTempResult = MsiDatabaseOpenView(hDB, "SELECT * FROM `RemoveRegistry`", hView);
if( nTempResult != ERROR_SUCCESS ) then
MsiCloseHandle( hDB );
return nTempResult;
endif;
// Execute the view
nTempResult = MsiViewExecute(hView, NULL);
if( nTempResult != ERROR_SUCCESS ) then
MsiCloseHandle( hDB );
return nTempResult;
endif;
// Create an empty MSI record
hRecord = MsiCreateRecord(5);
if( hRecord != NULL ) then
// Modify the MSI record
MsiRecordSetString(hRecord, 1, szRegistry);
MsiRecordSetInteger(hRecord, 2, iRoot);
MsiRecordSetString(hRecord, 3, szKey);
MsiRecordSetString(hRecord, 4, szName);
MsiRecordSetString(hRecord, 5, szComponent);
// Temporarily modify the running MSI database
nTempResult = MsiViewModify(hView, MSIMODIFY_INSERT_TEMPORARY, hRecord);
if( nTempResult != ERROR_SUCCESS ) then
// Log some error here!
else
// Log the success
endif;
else
nTempResult = ERROR_INSTALL_FAILURE;
endif;
MsiViewClose(hView);
return nTempResult;
end;
And make sure this code is scheduled for immediate execution, somewhere between InstallInitialize and RemoveRegistryValues.
I hope that helps.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 22, 2010
03:16 AM
Hello Reureu,
whatfor do you need "InstallMode" ?
Would you like to explain it shortly, please?
whatfor do you need "InstallMode" ?
Would you like to explain it shortly, please?
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 22, 2010
03:56 AM
Well, what I haven't detailed here is how it all fits together, but I mentioned it in a previous post in this thread:
The idea was to have a reasonably flexible implementation which allows to remove registry entries when a specific component is either installed or removed. This is why I had to take a component install mode into account.
The function I posted in my previous post was the function to add an entry in the RemoveRegistry table.
There are obviously 3 main functions
[LIST=1]
One that iterates through the RemoveRegistryConditional table.
One that allows to add an entry in the RemoveRegistry table (the one detailed in my previous post).
One that allows to add an entry in the Registry table.
and a few other helper functions.
Then I implemented an InstallScript custom action that iterates through the RemoveRegistryConditional table, checks the condition of each entry.
If the condition evaluates to MSICONDITION_TRUE, then it inserts the corresponding entry in either the Registry table and/or in the RemoveRegistry table, depending on the InstallMode value.
The idea was to have a reasonably flexible implementation which allows to remove registry entries when a specific component is either installed or removed. This is why I had to take a component install mode into account.
The function I posted in my previous post was the function to add an entry in the RemoveRegistry table.
There are obviously 3 main functions
[LIST=1]
and a few other helper functions.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 22, 2010
04:04 AM
Hi Reureu,
Thanks.
Can you post a portion of code, where you are
opening and reading the "RemoveRegistryConditional" Table, please ?
Thanks.
Can you post a portion of code, where you are
opening and reading the "RemoveRegistryConditional" Table, please ?
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 22, 2010
04:15 AM
Too easy.
It is the function that the InstallScript custom action calls.
The function you might still need is addItemToRegistryTable, but you can easily extrapolate it from addItemToRemoveRegistryTable already detailed in this thread.
/**
* This function iterates through the RemoveRegistryConditional table,
* checks the condition of every entry.
* If the condition evaluate to MSICONDITION_TRUE, the entry is inserted in
* -the Registry table if InstallMode == msidbRemoveRegistryOnInstall
* -the RemoveRegistry table if InstallMode == msidbRemoveRegistryOnRemove
* -both above tables if InstallMode == msidbRemoveRegistryOnBoth
* so that the registry entry/values get either deleted on installation of a specific component,
* or on deinstallation of a specific component.
@ param hMsi: handle to the installer
@ returns: -ERROR_SUCCESS if everything went smoothly
-Other error codes if any error occured when processing the MSI tables.
*/
function INT scheduleRegistryRemoval( hMsi )
HWND hDB;
HWND hView, hRecord;
NUMBER nBuffer;
STRING szRemoveRegistry;
NUMBER nRoot;
STRING szKey;
STRING szName;
STRING szComponent;
NUMBER nInstallMode;
STRING szCondition;
STRING szLogMsg;
NUMBER nTempResult;
INT iRet;
begin
nBuffer = 256;
// Open the MSI database
hDB = MsiGetActiveDatabase(hMsi);
if( hDB = NULL ) then
return ERROR_INSTALL_FAILURE;
endif;
// Open a view to the Feature table
nTempResult = MsiDatabaseOpenView(hDB, "SELECT * FROM `" + REMOVEREGISTRYCONDITIONAL_TABLE_NAME + "`", hView);
if( nTempResult != ERROR_SUCCESS ) then
MsiCloseHandle( hDB );
return ERROR_INSTALL_FAILURE;
endif;
nTempResult = MsiViewExecute(hView, NULL);
if( nTempResult != ERROR_SUCCESS ) then
MsiCloseHandle( hDB );
return ERROR_INSTALL_FAILURE;
endif;
// Iterate through all rows of the RemoveRegistryConditional table
while( MsiViewFetch(hView, hRecord) != ERROR_NO_MORE_ITEMS )
MsiRecordGetString( hRecord, 1, szRemoveRegistry, nBuffer );
nRoot = MsiRecordGetInteger( hRecord, 2 );
MsiRecordGetString( hRecord, 3, szKey, nBuffer );
MsiRecordGetString( hRecord, 4, szName, nBuffer );
MsiRecordGetString( hRecord, 5, szComponent, nBuffer );
nInstallMode = MsiRecordGetInteger( hRecord, 6 );
MsiRecordGetString( hRecord, 7, szCondition, nBuffer );
iRet = MsiEvaluateCondition(hMsi, szCondition);
if ( iRet = MSICONDITION_TRUE) then
if( ( nInstallMode & msidbRemoveRegistryOnInstall ) != 0 ) then
nTempResult = addItemToRemoveRegistryTable( hMsi, szRemoveRegistry, nRoot, szKey, szName, szComponent );
if( nTempResult != ERROR_SUCCESS ) then
MsiViewClose( hView );
return nTempResult;
endif;
endif;
if( ( nInstallMode & msidbRemoveRegistryOnRemove ) != 0 ) then
nTempResult = addItemToRegistryTable( hMsi, szRemoveRegistry, nRoot, szKey, szName, "", szComponent );
if( nTempResult != ERROR_SUCCESS ) then
MsiViewClose( hView );
return nTempResult;
endif;
endif;
endif;
endwhile;
MsiViewClose(hView);
return ERROR_SUCCESS;
end;
It is the function that the InstallScript custom action calls.
The function you might still need is addItemToRegistryTable, but you can easily extrapolate it from addItemToRemoveRegistryTable already detailed in this thread.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 22, 2010
04:27 AM
Thanks!
Thanks!
Thanks!
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 22, 2010
06:02 PM
It is working now - Thanks MUCH, Reureu!
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Sep 23, 2010
12:55 AM
No worries!
Feel free to suggest any improvement to the source code.
Feel free to suggest any improvement to the source code.