cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Kelter
Level 10

some help trying to save user settings on upgrade!

i need to make sure that certain registry values are retained after an upgrade (so the customer doesn't need to reconfigure after an upgrade).

Silly me, i figured this would be easily accomplished by (1)setting initial values in the property manager, (2)reading all the registry values of concern using the System Search view (such that any found values would overwrite the related properties), and then (3) set the reg values equal to the values of their associated properties.

what happens, unfortunately, is that all numeric values get written to the registry as string values with a "#" prepended, and all multi-string values get written as "String1[~]String2[~]String3[~]String4"

What's the MSI way of doing this? Can the correct behavior happen without scripting a whole mess of stuff?
Labels (1)
0 Kudos
(27) Replies
RobertDickau
Flexera Alumni

The trick might be to define your backup value in the Registry view as a string value, and not a multi-string value; at run time, Windows Installer interprets the [~] markers to turn it into a multi-string value.
0 Kudos
Kelter
Level 10

It seems that the value type is determined by the [~] markers, which seems to make sense...what i did to test this is to duplicate the registry entry 4 times as a cartesian product of (with leading/trailing [~], without leading\trailing [~]) and (creating the value as a multistring, creating the value as a string).

what i found initially, was that regardless of which choice was selected while creating the value, simply adding a leading or trailing [~] will change the value type at design time. this made me feel quite hopeful, so i ran my installation, and all four values on the target ended up as a single string in the first location of a multistring value.

While we're trying to fix this problem, how about the issue with numerical values and the prepended "#"? maybe these problems are related?

---

am i wrong, or in most APIs that support reading and writing data, isn't there typically an underlying symmetry such that a value read in with said API could be written out without modification... i mean, if you read a value from a location, then write the read value back out to the same location, there shouldn't really be a change...that is, you shouldn't have to modify the data that you just read just to keep it the same as it was when you read it... so once we get down to it, either (a) there is some other method that i should be using, (b) the MSI interface lacks this reflexive logic, or (c) installshield corrupts the data somewhere along the way... i'm holding out hope for (a).
0 Kudos
Kelter
Level 10

if I had any reason to believe that this would be such a mess, I would have scripted it all myself…but there are just too many good reasons to use the official MSI method… cheifly among them is the ability of the MSI logic to properly handle rollbacks and…UPGRADES!!!!

Thanks to Robert for your attention so far. I really hope you can help with this. I've seen a few other threads with this issue, and the only ones with solutions involve custom actions. Mostly, though, the issue never gets an answer. is there an MSI way of doing this, or should i just go back to square 1?
0 Kudos
RobertDickau
Flexera Alumni

I think it is the same issue; please see the "Registry Table" topic. I gather creating a plain string value containing [PROP_NAME] will convert value types at run time based on #, internal [~], and so on.

For hard-coded values in your project, InstallShield provides the DWORD and REG_MULTI_SZ types in the project to save you from having to enter or know those special markers, but it does have the effect you saw when expanded property values enter into it.
0 Kudos
Kelter
Level 10

i think what the real problem is is that the interpretation of prefixes happens before the property expansion, and it should be after...does that make sense? i'm guessing that that's handled by MSI logic and not IS logic, and gets back to the r/w symmetry issue earlier...if a system search is going to read a value, then prepend the prefix, then store the value in a property, then should the reg table logic expand the property, then interpret the prefix, then write the value?

i just did a test where i created a string value, and set it equal to a property...the property was set to "#3", and the value was written to the registry as a DWORD...yippee!!!!!!! this seems to back up your statement, and gives me a little bit of hope. the trouble still remains that this is not happening with the multistring value. here's the scenario:
[CODE]
Properties
[MULTI_STRING_RAW] = String1[~]String2[~]String3
[MULTI_STRING_WB] = [~]String1[~]String2[~]String3[~]

Registry values
Test value 1
Name: MultiString
Value: [~][MULTI_STRING_RAW][~]
TestValue 2
Name: MultiStringWithBrackets
Value: [~][MULTI_STRING_WB][~]
TestValue 3
Name: StringWithoutBrackets
Value: [MULTI_STRING_RAW]
TestValue 4
Name: StringWithBrackets
Value: [MULTI_STRING_WB]

Actual values/types
MultiString: (REG_MULTI_SZ)
String1[~]String2[~]String3 (as one string)
MultiStringWithBrackets: (REG_MULTI_SZ)
[~]String1[~]String2[~]String3[~] (as one string)
StringWithoutBrackets: (REG_SZ)
String1[~]String2[~]String3 (as one string)
StringWithBrackets: (REG_SZ)
[~]String1[~]String2[~]String3[~] (as one string)
[/CODE]

Does that help? I really thought StringWithBrackets would work since a string value defined as a property defined as #3 properly resulted in a DWORD value (3) being written into the reg.

One step closer, thanks again to Robert!!!!
0 Kudos
RobertDickau
Flexera Alumni

I think my understanding is the same as yours: My quick test this morning was to set up a system search for a registry value, storing whatever it reads into property MY_REG_DATA; and in the Registry view, created a string value called "backup" with value [MY_REG_DATA].

At run time, if the registry value was a plain string, the backup was written as a plain string; if the value was a multi-string, the backup was written as a multi-string. I didn't need to add [~] as a prefix or suffix or anything.
0 Kudos
Kelter
Level 10

alright...so it sounds like i need to create two components for each of these keys; one will be a multistring and contain the default value, and the other will be a string value and contain whatever was read in during AppSearch. I'll use the "found" value as a condition for the component that will restore the old value, and the complement of that value will be the condition for the component with the hard-coded default value. this is annoying, but tolerably so. 🙂

okay, now the actual results...
[CODE]Here's the line from AppSearch
MSI (c) (64:80) [15:56:27:906]:
PROPERTY CHANGE: Modifying RTX_SVC_RTSS_001_DEPENDONSERVICE property.
Its current value is 'Rtx_HalExt[~]Rtx_rtss[~]RtxServer[~]Rtss_010'.
Its new value: ''.

And here's the line from ExecuteAction
MSI (s) (A8:7C) [15:59:00:125]:
PROPERTY CHANGE: Modifying RTX_SVC_RTSS_001_DEPENDONSERVICE property.
Its current value is 'Rtx_HalExt[~]Rtx_rtss[~]RtxServer[~]Rtss_010'.
Its new value: ' ACTION=INSTALL'.
[/CODE]

This doesn't make any sense! Okay, this is just a shot in the dark, but here's what i'm thinking: near the top of the ExecuteAction section of the log, a command line gets dumped to the log. Strangely, there's a mixture of about 38 random property names/value pairs and directory id/value pairs on this commandline. I don't why they would be on the commandline, but since the value as it is reported in the log looks truncated (after around 1100 chars) i'm thinking that possibly there is a buffer overflow that isn't being caught, and as a result, some data (including this property value) is being trampled.

At any rate, i'm not familiar enough with the stuff that happens at the beginning of "ExecuteAction" so that's the best conjecture i can make. (Oh, this is actually IS'08', by the way...)
0 Kudos
RobertDickau
Flexera Alumni

A couple of tiny things: Instead of using two components, can you test if the AppSearch property is set, and if not, use a set-property custom action to populate the property with the default value? Using a set-property action to set a value to one[~]two[~]three seems to work.

Stepping back a bit, presumably the situation is such that omitting a feature from the Remove field of the Upgrade table (see "Upgrade Table") wouldn't help; nor would moving RemoveExistingProducts from remove-then-install to install-then-remove-unused? Does upgrade validation tell you anything?
0 Kudos
Kelter
Level 10

that makes alot more sense, and i'm sure runtime component objects are more resource heavy than custom actions. i'll use your suggestion, and let you know if that changes anything.

this is the first version of our product that will support upgrades, so i don't want to take any chances...and the full uninstall\reinstall is documented as the "safer" method. also, for licensing purposes, i want the install package to fully remove the previous version, before installing and licensing the new version. "omitting a feature from the REMOVE property" sounds to me like "maintenance nightmare", but perhaps i'm being presumptuous.

i think the first of your "tiny things" is probably be the proper MSI way to handle this pattern. I'll write back "post-eureka" to share my joy and excitement...
0 Kudos
Kelter
Level 10

okay, the weirdness of last night persists. here's some log stuff:

This line from AppSearch shows the initial value being overwritten
[CODE]MSI (c) (84:BC) [10:08:19:484]: PROPERTY CHANGE: Modifying THE_PROPERTY_IN_QUESTION property. Its current value is 'String1[~]String2[~]String3[~]String4'. Its new value: ''.[/CODE]
This seems wrong, since it read in the multistring value, but I initially assumed that this was just a symptom of trying to write a value to the log that starts with a NULL...

But...looky here:

This is the top of the Execute action. Notice the change in the value of THE_PROPERTY_IN_QUESTION
[CODE]MSI (c) (84:BC) [10:08:29:578]: Doing action: ExecuteAction
Action start 10:08:29: ExecuteAction.
MSI (c) (84:BC) [10:08:29:593]: PROPERTY CHANGE: Adding SECONDSEQUENCE property. Its value is '1'.
MSI (c) (84:BC) [10:08:29:593]: Grabbed execution mutex.
MSI (c) (84:BC) [10:08:29:593]: Incrementing counter to disable shutdown. Counter after increment: 0
MSI (c) (84:BC) [10:08:29:609]: Switching to server: SECONDSEQUENCE="1" SS_ERROR="FALSE" WINDOWS7MP_ERR="FALSE" SERVER03SP2_ERR="FALSE" NOTHINGINSTALLED="FALSE" TOPLEVELINST="TRUE" TOPLEVELINSTB="FALSE" TOPLEVELINSTA="TRUE" EMBSTATEINST="FALSE" TOOLSTATEINST="TRUE" TOOLSTATEINSTB="FALSE" TOOLSTATEINSTA="TRUE" VSSTATEINST="FALSE" DOCSTATEINST="TRUE" NOTHINGCHANGED="FALSE" USBCHANGE="TRUE" TOPLEVELCHANGED="TRUE" EMBSTATECHANGE="FALSE" TOOLSTATECHANGE="TRUE" VSSTATECHANGE="FALSE" DOCSTATECHANGE="TRUE" SSCHANGED="TRUE" REGSUCCESS=********** OEM="1" PROCESSORS=********** VSSUPPORT=********** OSSUPPORT=********** ALLUSERS="1" MSDEV981="C:\Program Files\\\Visual Studio 6.0\MSDEV98\" ADDINS="C:\Program Files\\\Visual Studio 6.0\MSDEV98\Addins\" TARGETDIR="E:\" ALLUSERSPROFILE="C:\Documents and Settings\All Users\" INSTALLDIR="C:\Program Files\\\" ASSEMBLIES="C:\Program Files\\\assemblies\" BIN2="C:\Program Files\\\bin\" BIN3="C:\Program Files\\\bin\" _10="C:\WINDOWS\\010\" BIN5="C:\Program Files
MSI (s) (28:00) [10:08:29:625]: Grabbed execution mutex.
MSI (s) (28:AC) [10:08:29:625]: Resetting cached policy values
MSI (s) (28:AC) [10:08:29:625]: Machine policy value 'Debug' is 0
MSI (s) (28:AC) [10:08:29:625]: ******* RunEngine:
******* Product: C:\Documents and Settings\Administrator\Local Settings\Application Data\Downloaded Installations\{C8126D8C-EB28-44FF-910C-34D2801CF74A}\ 2009.msi
******* Action: INSTALL
******* CommandLine: **********
MSI (s) (28:AC) [10:08:29:625]: Machine policy value 'DisableUserInstalls' is 0
MSI (s) (28:AC) [10:08:29:625]: File will have security applied from OpCode.
MSI (s) (28:AC) [10:08:30:531]: SOFTWARE RESTRICTION POLICY: Verifying package --> 'C:\Documents and Settings\Administrator\Local Settings\Application Data\Downloaded Installations\{C8126D8C-EB28-44FF-910C-34D2801CF74A}\ 2009.msi' against software restriction policy
MSI (s) (28:AC) [10:08:30:531]: Note: 1: 2262 2: DigitalSignature 3: -2147287038
MSI (s) (28:AC) [10:08:30:531]: SOFTWARE RESTRICTION POLICY: C:\Documents and Settings\Administrator\Local Settings\Application Data\Downloaded Installations\{C8126D8C-EB28-44FF-910C-34D2801CF74A}\ 2009.msi is not digitally signed
MSI (s) (28:AC) [10:08:30:531]: SOFTWARE RESTRICTION POLICY: C:\Documents and Settings\Administrator\Local Settings\Application Data\Downloaded Installations\{C8126D8C-EB28-44FF-910C-34D2801CF74A}\ 2009.msi is permitted to run at the 'unrestricted' authorization level.
MSI (s) (28:AC) [10:08:30:531]: End dialog not enabled
MSI (s) (28:AC) [10:08:30:531]: Original package ==> C:\Documents and Settings\Administrator\Local Settings\Application Data\Downloaded Installations\{C8126D8C-EB28-44FF-910C-34D2801CF74A}\ 2009.msi
MSI (s) (28:AC) [10:08:30:531]: Package we're running from ==> C:\WINDOWS\Installer\40e9192.msi
MSI (s) (28:AC) [10:08:30:546]: APPCOMPAT: looking for appcompat database entry with ProductCode '{00000000-0000-0000-0000-000000000000}'.
MSI (s) (28:AC) [10:08:30:546]: APPCOMPAT: no matching ProductCode found in database.
MSI (s) (28:AC) [10:08:30:546]: MSCOREE already loaded, using loaded copy
MSI (s) (28:AC) [10:08:30:546]: Machine policy value 'TransformsSecure' is 0
MSI (s) (28:AC) [10:08:30:546]: User policy value 'TransformsAtSource' is 0
MSI (s) (28:AC) [10:08:30:546]: Machine policy value 'DisablePatch' is 0
MSI (s) (28:AC) [10:08:30:546]: Machine policy value 'AllowLockdownPatch' is 0
MSI (s) (28:AC) [10:08:30:546]: Machine policy value 'DisableLUAPatching' is 0
MSI (s) (28:AC) [10:08:30:546]: Machine policy value 'DisableFlyWeightPatching' is 0
MSI (s) (28:AC) [10:08:30:546]: APPCOMPAT: looking for appcompat database entry with ProductCode '{00000000-0000-0000-0000-000000000000}'.
MSI (s) (28:AC) [10:08:30:546]: APPCOMPAT: no matching ProductCode found in database.
MSI (s) (28:AC) [10:08:30:546]: Transforms are not secure.
MSI (s) (28:AC) [10:08:30:562]: Command Line: SECONDSEQUENCE=1 SS_ERROR=FALSE WINDOWS7MP_ERR=FALSE SERVER03SP2_ERR=FALSE NOTHINGINSTALLED=FALSE TOPLEVELINST=TRUE TOPLEVELINSTB=FALSE TOPLEVELINSTA=TRUE EMBSTATEINST=FALSE TOOLSTATEINST=TRUE TOOLSTATEINSTB=FALSE TOOLSTATEINSTA=TRUE VSSTATEINST=FALSE DOCSTATEINST=TRUE NOTHINGCHANGED=FALSE USBCHANGE=TRUE TOPLEVELCHANGED=TRUE EMBSTATECHANGE=FALSE TOOLSTATECHANGE=TRUE VSSTATECHANGE=FALSE DOCSTATECHANGE=TRUE SSCHANGED=TRUE REGSUCCESS=********** OEM=1 PROCESSORS=********** VSSUPPORT=********** OSSUPPORT=********** ALLUSERS=1 MSDEV981=C:\Program Files\\\Visual Studio 6.0\MSDEV98\ ADDINS=C:\Program Files\\\Visual Studio 6.0\MSDEV98\Addins\ TARGETDIR=E:\ ALLUSERSPROFILE=C:\Documents and Settings\All Users\ INSTALLDIR=C:\Program Files\\\ ASSEMBLIES=C:\Program Files\\\assemblies\ BIN2=C:\Program Files\\\bin\ BIN3=C:\Program Files\\\bin\ _10=C:\WINDOWS\\010\ BIN5=C:\Program Files\\\bin\ SAMPLES=C:\Program Files\\\samples\
MSI (s) (28:AC) [10:08:30:562]: PROPERTY CHANGE: Adding PackageCode property. Its value is '{C8126D8C-EB28-44FF-910C-34D2801CF74A}'.
MSI (s) (28:AC) [10:08:30:562]: Product Code passed to Engine.Initialize: ''
MSI (s) (28:AC) [10:08:30:562]: Product Code from property table before transforms: '{00000000-0000-0000-0000-000000000000}'
MSI (s) (28:AC) [10:08:30:562]: Product Code from property table after transforms: '{00000000-0000-0000-0000-000000000000}'
MSI (s) (28:AC) [10:08:30:562]: Product not registered: beginning first-time install
MSI (s) (28:AC) [10:08:30:562]: PROPERTY CHANGE: Adding ProductState property. Its value is '-1'.
MSI (s) (28:AC) [10:08:30:562]: Entering CMsiConfigurationManager::SetLastUsedSource.
MSI (s) (28:AC) [10:08:30:562]: User policy value 'SearchOrder' is 'nmu'
MSI (s) (28:AC) [10:08:30:562]: Adding new sources is allowed.
MSI (s) (28:AC) [10:08:30:562]: PROPERTY CHANGE: Adding PackagecodeChanging property. Its value is '1'.
MSI (s) (28:AC) [10:08:30:562]: Package name extracted from package path: ' 2009.msi'
MSI (s) (28:AC) [10:08:30:562]: Package to be registered: ' 2009.msi'
MSI (s) (28:AC) [10:08:30:562]: Note: 1: 2729
MSI (s) (28:AC) [10:08:30:562]: Note: 1: 2729
MSI (s) (28:AC) [10:08:30:562]: Note: 1: 2262 2: AdminProperties 3: -2147287038
MSI (s) (28:AC) [10:08:30:562]: PROPERTY CHANGE: Adding ALLUSERS property. Its value is '1'.
MSI (s) (28:AC) [10:08:30:562]: Machine policy value 'DisableMsi' is 0
MSI (s) (28:AC) [10:08:30:562]: Machine policy value 'AlwaysInstallElevated' is 0
MSI (s) (28:AC) [10:08:30:562]: User policy value 'AlwaysInstallElevated' is 0
MSI (s) (28:AC) [10:08:30:562]: Product installation will be elevated because user is admin and product is being installed per-machine.
MSI (s) (28:AC) [10:08:30:562]: Running product '{00000000-0000-0000-0000-000000000000}' with elevated privileges: Product is assigned.
...

...
MSI (s) (28:AC) [10:08:30:578]: PROPERTY CHANGE: Modifying THE_PROPERTY_IN_QUESTION property. Its current value is 'String1[~]String2[~]String3[~]String4'. Its new value: ' ACTION=INSTALL'.
MSI (s) (28:AC) [10:08:30:578]: Engine has iefSecondSequence set to true.
MSI (s) (28:AC) [10:08:30:578]: TRANSFORMS property is now:
MSI (s) (28:AC) [10:08:30:578]: PROPERTY CHANGE: Deleting SOURCEDIR property. Its current value is 'C:\Documents and Settings\Administrator\Local Settings\Application Data\Downloaded Installations\{C8126D8C-EB28-44FF-910C-34D2801CF74A}\'.
MSI (s) (28:AC) [10:08:30:578]: PROPERTY CHANGE: Adding VersionDatabase property. Its value is '200'.[/CODE]

I repeated my original test as the StringWithoutBrackets value is just what you were talking about. This, and MultiString both got written as " ACTION=INSTALL".

Does this help at all?
0 Kudos
RobertDickau
Flexera Alumni

I haven't personally seen that before; to see if it has to do with the total size of the properties passed from UI to Execute, perhaps see if a new project that only reads and backs up the data behaves differently? (And with the original log, does InstallShield's log file analyzer tell you anything more?)

If it turns out to be the length of the set of properties, perhaps see if you can change some of the project's properties from public to private?
0 Kudos
Kelter
Level 10

Okay, here's the full log from the tiny little test project. I still end up with " Action: INSTALL" for a value. Why does InstallShield hate me? :confused:
0 Kudos
Kelter
Level 10

could i send you the project test project so you can see what could be going wrong? doesn't this sound like a bug?
0 Kudos
RobertDickau
Flexera Alumni

At this level of detail, it's not clear whether it's the Windows Installer engine or something in the project that's causing what you're seeing. The previous attachment had only a couple of lines from the log file; in the smaller test project, do the final property values---the Property(C) and Property(S) entries---in a full log file show up any differently? Does it work with a different key and multi-string value that you create by hand? Do MSI validation or the InstallShield log file analyzer tell you anything more?

(I'm afraid I personally don't have the resources to do a timely detailed investigation; you're might post a project in case there are other volunteers, or it might be worth working with Support to get a timely answer...)
0 Kudos
Kelter
Level 10

Hey, you know what would have been really smart? If i had attached the correct file in the first place! 😛 check the file now attached to that post. 😮
0 Kudos
RobertDickau
Flexera Alumni

The final properties don't seem to be in there; perhaps create and examine a verbose log (msiexec /i prod.msi /L*v everything.log)?

A stab in the dark, but does THE_PROPERTY_IN_QUESTION appear in SecureCustomProperties?
0 Kudos
Kelter
Level 10

i usually just do /lv, but i'll do a /lv* this time (and i'll be interested to see the difference, also); and yes, it's appearing in SecureCustomProperties (probably did that automatically, since it was part of a System Search).
0 Kudos
Kelter
Level 10

here it is. i hope this helps.

i noticed on line 1218 that the correct value is reported, but " ACTION=INSTALL" is what actually gets written into the reg.
0 Kudos
RobertDickau
Flexera Alumni

Nothing jumps out; in line 00301 of the analyzed log file, I see that "ACTION=INSTALL" is listed twice, for some reason, the second time after your THE_PROP= entry.

As a test, does an example with a different hand-made registry value act differently? Or skipping the AppSearch and using a property value set by a custom action or in the Property table?
0 Kudos
Kelter
Level 10

what kind of "different" do you mean? not sure what variable you're trying to tweak. I've tried different strings in a multistring, and different value types, and the other value types are working fine (thanks to your help with the DWORDs) and the values in the multistring don't seem to make a difference.

from my post on 1/6:3:17 -- i tried to simply set a property or two (in the property manager) to the EXACT value that had previously been hard coded in the registry table.

maybe i'm missing your point...
0 Kudos