Community Forums
Results 1 to 3 of 3

Thread: How to read and write REG_MULTI_SZ values

  1. #1
    Join Date
    May 2005
    Location
    San Diego, CA
    Posts
    9

    How to read and write REG_MULTI_SZ values

    About 9 months ago, I searched long and hard to find GOOD examples of reading and writing REG_MULTI_SZ values using InstallScript. Unfortunately, I was unable to find any.

    I put together these two functions which have been in our installers for quite awhile now. I have not had a single problem with either function.

    Feel free to use.

    John Bolton

    Adding a value:
    Code:
    function BOOL AddStringToRegMultiSZ(nDefaultRoot, szRegistryKey, szRegistryValue, szString)
    	LIST	listStrings;
    	NUMBER	nType;
    	NUMBER	nvCurrentStringSize;
    	NUMBER	nvReturnCode;
    	NUMBER	nvResultCode;
    	NUMBER	nvNewStringSize;
    	STRING	svCurrentStringValue;
    	STRING	szUpdatedStringValue[32000]; // I hate magic numbers, but I don't know the max size of a REG_MULTI_SZ value.
    	STRING	szTemp[32000];
    begin
    	Disable(LOGGING);
    	nType = REGDB_STRING_MULTI;
    	listStrings = ListCreate(STRINGLIST);
    	nvCurrentStringSize = 0;
    	nvReturnCode = 0;
    	
    	RegDBSetDefaultRoot(nDefaultRoot);
    	nvReturnCode = RegDBGetKeyValueEx(szRegistryKey, szRegistryValue, nType, svCurrentStringValue, nvCurrentStringSize); 	
    	if (nvReturnCode = 0) then 
    		if (nvCurrentStringSize > 0) then
    			// Get current strings from value
    			nvReturnCode = StrGetTokens(listStrings, svCurrentStringValue, ""); 
    			if (nvReturnCode != 0) then
    				LogMessage("AddStringToRegMultiSZ(): StrGetTokens() returned an error: " + FormatMessage(nvReturnCode));
    				ListDestroy(listStrings);
    				return FALSE;
    			endif;
    			
    			// Add our string to the list of strings
    			nvReturnCode = ListAddString(listStrings, szString, AFTER);
    			if (nvReturnCode < ISERR_SUCCESS) then
    				LogMessage("AddStringToRegMultiSZ(): ListAddString() returned an error: " + FormatMessage(nvReturnCode));
    				ListDestroy(listStrings);
    				return FALSE;
    			endif;
    		endif;
    	else 	// registry value does not exist, create our own
    			nvReturnCode = ListAddString(listStrings, szString, AFTER);
    			if (nvReturnCode < ISERR_SUCCESS) then
    				LogMessage("AddStringToRegMultiSZ(): ListAddString() returned an error: " + FormatMessage(nvReturnCode));
    				ListDestroy(listStrings);
    				return FALSE;
    			endif;
    	endif; 
    
    	// Prepare the string as a multi string registry value
    	nvReturnCode = StrPutTokens(listStrings, szUpdatedStringValue, "", TRUE);
    	if (nvReturnCode != 0) then
    		LogMessage("AddStringToRegMultiSZ(): StrPutTokens() returned an error: " + FormatMessage(nvReturnCode));
    		ListDestroy(listStrings);
    		return FALSE;
    	endif;
    	
    	// Get size of null delimited string
    	szTemp = szUpdatedStringValue;
    	CharReplace(szTemp, STRTOCHAR('\0'), STRTOCHAR('|'), 0);
    	nvNewStringSize = StrLengthChars(szTemp);
    	
    	// Update registry value with new strings 
    	nvReturnCode = RegDBSetKeyValueEx(szRegistryKey, szRegistryValue, nType, szUpdatedStringValue, (nvNewStringSize + 2)); // add two for the two null chars at the end
    	if (nvReturnCode != 0) then
    		LogMessage("AddStringToRegMultiSZ(): RegDBSetKeyValueEx() returned an error: " + FormatMessage(nvReturnCode));
    		ListDestroy(listStrings);
    		return FALSE;
    	endif;
    
    	ListDestroy(listStrings);
    	Enable(LOGGING);
    	
    	return TRUE;
    end;
    Removing a value:

    Code:
    function BOOL RemoveStringFromRegMultiSZ(nDefaultRoot, szRegistryKey, szRegistryValue, szString)
    	LIST	listStrings;
    	NUMBER	nType;
    	NUMBER	nvCurrentStringSize;
    	NUMBER	nvReturnCode;
    	NUMBER	nvResultCode;
    	NUMBER	nvNewStringSize;
    	NUMBER	nvListCount;
    	STRING	svCurrentStringValue;
    	STRING	szUpdatedStringValue[32000]; // I hate magic numbers, but I don't know the max size of a REG_MULTI_SZ value.
    	STRING	svListString;
    	STRING	svCurrentListString;
    	STRING	szTemp[32000];
    begin
    	Disable(LOGGING);
    	nType = REGDB_STRING_MULTI;
    	listStrings = ListCreate(STRINGLIST);
    	nvCurrentStringSize = 0;
    	nvReturnCode = 0;
    	
    	RegDBSetDefaultRoot(nDefaultRoot);
    	nvReturnCode = RegDBGetKeyValueEx(szRegistryKey, szRegistryValue, nType, svCurrentStringValue, nvCurrentStringSize); 	
    	if (nvReturnCode = 0) then 
    		if (nvCurrentStringSize > 0) then
    			// Get current strings from value
    			nvReturnCode = StrGetTokens(listStrings, svCurrentStringValue, ""); 
    			if (nvReturnCode != 0) then
    				LogMessage("RemoveStringFromRegMultiSZ(): StrGetTokens() returned an error: " + FormatMessage(nvReturnCode));
    				ListDestroy(listStrings);
    				return FALSE;
    			endif;
    			nvListCount = ListCount(listStrings);
    			
    			// iterate through list of strings, deleting ones matching the incoming szString.
    			nvResultCode = ListGetFirstString(listStrings, svListString);
    			while (nvResultCode != END_OF_LIST)
    				ListCurrentString(listStrings, svCurrentListString); 
    				if (StrCompare(svCurrentListString, szString) = 0) then // strings are the same
    					nvReturnCode = ListDeleteString(listStrings);
    					if (nvReturnCode != 0) then
    						LogMessage("RemoveStringFromRegMultiSZ(): ListDeleteString() returned an error: " + FormatMessage(nvReturnCode));
    						ListDestroy(listStrings);
    						return FALSE;
    					endif;
    				endif;
    				nvResultCode = ListGetNextString(listStrings, svListString);
    			endwhile;
                nvListCount = ListCount(listStrings);
    			// Prepare the string as a multi string registry value
    			nvReturnCode = StrPutTokens(listStrings, szUpdatedStringValue, "", TRUE);
    			if (nvReturnCode != 0) then
    				LogMessage("RemoveStringFromRegMultiSZ(): StrPutTokens() returned an error: " + FormatMessage(nvReturnCode));
    				ListDestroy(listStrings);
    				return FALSE;
    			endif;
    			
    			// Get size of null delimited string
    			szTemp = szUpdatedStringValue;
    			CharReplace(szTemp, STRTOCHAR('\0'), STRTOCHAR('|'), 0);
    			nvNewStringSize = StrLengthChars(szTemp);
    			
    			// Update registry value with new strings 
    			nvReturnCode = RegDBSetKeyValueEx(szRegistryKey, szRegistryValue, nType, szUpdatedStringValue, (nvNewStringSize + 2)); // add two for the two null chars at the end
    			if (nvReturnCode != 0) then
    				LogMessage("RemoveStringFromRegMultiSZ(): RegDBSetKeyValueEx() returned an error: " + FormatMessage(nvReturnCode));
    				ListDestroy(listStrings);
    				return FALSE;
    			endif;
    		endif;
        else
        	LogMessage("RemoveStringFromRegMultiSZ(): Unable to read current values from registry value. Error: " + FormatMessage(nvReturnCode));
        	return FALSE;
    	endif;
    	
    	ListDestroy(listStrings);
    	Enable(LOGGING); 
    	
    	return TRUE;
    end;

  2. #2
    Join Date
    Jun 2005
    Posts
    16

    Smile Nice implementation but

    You don't need the fixed size of 3200 because installshield automatically allocated the memory needed.
    One improvement
    Generally this function are used to set the groupOrderList registry entry, in this case it is useful to add another string parameter for deciding where to add the new string (after which string in the order)
    But great job;

  3. #3
    Join Date
    Jan 2018
    Posts
    2

    Question Where's the Beef

    Hi John Bolton,
    Thank you for your post. I found it very useful, but i was unable to get my own function to work. I have added a link to my post if you can help. I am wondering about your code, are you assuming that the last two characters of the string written to the registry will be NULL or is there somewhere that you are initializing them?



    https://community.flexerasoftware.co...478#post518478

    Thanks,
    Brent

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •