PDA

View Full Version : Ask user which registry key they want to use



AndrewFishwick
11-02-2012, 05:17 AM
I'm developing an installer for a piece of software my company has created. The software relies on OpenEdge, and the version that the customer (the user of my installer) may be using can vary between lets say 10, 11 and 12. These versions are all stored in the registry.


HKEY_CURRENT_USER\Software\PSC\PROGRESS\10 would be settings for version 10 for example.

At the minute I am doing a system search for a value inside
HKEY_CURRENT_USER\Software\PSC\PROGRESS\10 and saving that to the property PROWINDIR.

I need to read the PROGRESS key/folder, check what subfolders/children it has and then ask the user which they would like to use. When the user has selected, I grab the value I need and store it (into PROWINDIR) for use in a shortcut argument later on.

I was wondering if this is possible (reading children of a specific registry folder, and prompting the user to choose which they want) and if so, how might I go about doing it.

Thanks

RobertDickau
11-02-2012, 06:05 PM
If you're using an MSI project, the system search functionality (Windows Installer's AppSearch action and related tables) don't, alas, handle sub-key searches.

If there's a limited set of versions to find, you could include multiple "searches". Otherwise, a custom action could enumerate the subkeys and display them somehow. (InstallScript has RegDBQueryKey, for example, and you could use the results to populate a custom dialog box.) If you decide to go down that route, someone here could help you get started.

AndrewFishwick
11-06-2012, 03:47 AM
If you're using an MSI project, the system search functionality (Windows Installer's AppSearch action and related tables) don't, alas, handle sub-key searches.

I am. Is that bad? I tried googling sub-key searches and nothing useful really came up, what are they and how should I implement them?


If there's a limited set of versions to find, you could include multiple "searches". Otherwise, a custom action could enumerate the subkeys and display them somehow. (InstallScript has RegDBQueryKey, for example, and you could use the results to populate a custom dialog box.) If you decide to go down that route, someone here could help you get started.

The installer should be futureproof in that it finds all versions, no matter how new. For example, OpenEdge 13.2 could come out and I need to find that, so I can't do multiple searches. If there is a way to list all sub keys inside the "PROGRESS" key, output them and let the user choose which to use I would like to do that.

RobertDickau
11-07-2012, 03:32 PM
It's a good idea to use an MSI project, though (as in this instance) there are some limitations to its built-in functionality.

Knowing that, you can (for example) create an InstallScript custom action that calls RegDBQueryKey and populates a custom dialog box. It's a bit tricky, but we can provide some pointers if that's where you'd like to go.

AndrewFishwick
11-08-2012, 08:44 AM
Yeah it seems like that is my only option. I haven't worked with InstallScript yet, I've tried to avoid it as my programming skills aren't very strong and so have done everything with Installshield.

Basically I need to read any sub keys under


HKEY_CURRENT_USER\Software\PSC\PROGRESS

Let the user pick one, and then grab a value (installPath) from the key that the user chose.

Is that possible? and if so how would I start?

RobertDickau
11-10-2012, 04:22 PM
It is possible, but to be frank it's a fair amount of work. (There are many reasons to favor Basic MSI installers, but when you have specialized requirements, programming often comes into it.)

Some of the first pieces to look into are:


Creating an InstallScript custom action
Calling RegDBQueryKey in your custom action
Taking the results and writing to the MSI database so they show up as choices in a dialog box and you can get the user's selection; see this old newsletter tip (http://www.flexerasoftware.com/webdocuments/PDF/msiaccess.pdf) for the general idea and examples

(A word from our sponsors: we also talk about this technique in some detail in the Advanced Windows Installer Using InstallShield (http://www.flexerasoftware.com/services/education/installshield-advanced-msi.htm) course.)

AndrewFishwick
11-12-2012, 10:22 AM
Thanks for all the help Rob.

I have started on the InstallScript and figured something like this would be good:


function MyFunction(hMSI)

int listResults;
string listArray;

begin

// read keys from registry
RegDBQueryKey ( "HKEY_CURRENT_USER\Software\PSC\PROGRESS" , REGDB_KEYS , listResults );
// listResults has to be an int for some reason, not sure what value its returning, hoped it would be an array of the sub keys

// split to specific items
ListAppendToArray ( listArray , listResults , TRUE );

// assign key to property
MsiSetProperty ( ISMSI_HANDLE , "FIRSTKEY" , listArray(0) );

end;

However:

a) listResults seems to have to be an int, why is that? Surely I am getting some sort of array/list/string with the subkeys, not an integer?
b) I am getting this error:


[InstallShieldPath]\Script Files\Setup.rul(62) : internal error : InstrcCompile

Line 62 is the "MsiSetProperty();" one.

I'm sort of stumped, and probably doing this wrong, any chance you can help me?

RobertDickau
11-12-2012, 03:27 PM
Please see the help topic "RegDBQueryKey Example" for a few extra steps. You'll need to create the list variable with ListCreate; call RegDBSetDefaultRoot to point to HKEY_CURRENT_USER and leave it out of RegDBQueryKey; and afterward call (for example) ListGetFirstString to get the first item.

Hysteresis
11-15-2012, 12:17 PM
This example shows how to use LISTs. Obviously change the key root, key and functionality to your requirements:



function void AdjustPCBaXComponentRefCount( hMSI, szPCBAXVersion )
// Declare local variables.
STRING svKeyVal[MAX_KEY_VALUE];
LIST listKeyValues;
NUMBER nVal;
begin

WriteInstallLog( hMSI, "...adjust PCBaX component reference count in registry...", INFORMATION );

// Create a list to hold the key values;
listKeyValues = ListCreate( STRINGLIST );
// If an error occurred, report it; then return.
if (listKeyValues = LIST_NULL) then
MessageBoxSilent( hMSI, "AdjustPCBaXComponentRefCount: Unable to create list", SEVERE );
return;
endif;

// Set root key before calling other RegDB functions
if ( RegDBSetDefaultRoot( HKEY_LOCAL_MACHINE ) = 0 ) then
if ( RegDBQueryKey ( CBMR_REG_SHARED_COMPONENTS,
REGDB_NAMES, listKeyValues ) = 0 ) then

// Parse key list looking for CBMR components
nVal = ListGetFirstString( listKeyValues, svKeyVal );

// Immediate exit if no key values found in specified key
if ( nVal != END_OF_LIST ) then
// Read the Key value
repeat

// Process the key - is it 1 of ours ?
if ( svKeyVal % szPCBAXVersion ) then
// Ensure ref count of our components are always
// set to 1
//MessageBoxSilent( hMSI, "AdjustPCBaXComponentRefCount: Adjusting count for "+svKeyVal,
// INFORMATION );
if ( RegDBSetKeyValueEx ( CBMR_REG_SHARED_COMPONENTS,
svKeyVal, REGDB_NUMBER,
"1", -1 ) != 0 ) then
MessageBoxSilent( hMSI, "AdjustPCBaXComponentRefCount: Unable to set reg entry", SEVERE );
// Tidyup
ListDestroy( listKeyValues );
return;
endif;
endif;

// Get next key value
nVal = ListGetNextString( listKeyValues, svKeyVal );
until nVal = END_OF_LIST;
endif;
endif;
else
MessageBoxSilent( hMSI, "AdjustPCBaXComponentRefCount: Unable to set HKLM", SEVERE );
endif;

// Tidyup
ListDestroy( listKeyValues );

end;