WiX RegistrySearch is failing for MultiString

2019-08-14 19:32发布

问题:

I am facing issue for RegistrySearch for multistring, where as string search working fine. Checked in installation logs

Action start 13:40:07: AppSearch. MSI (s) (40:E0) [13:40:07:381]: PROPERTY CHANGE: Adding MYKEY property. Its value is ''. MSI (s) (40:E0) [13:40:07:381]: PROPERTY CHANGE: Adding MYSERVICE property. Its value is 'myvalue2'.

I have trimmed some logs here

Action ended 13:40:51: ScheduleReboot. Return value 1. Action ended 13:40:51: INSTALL. Return value 1. You must restart your system for the configuration changes made to XXXXX to take effect. Click Yes to restart now or No if you plan to manually restart later. Property(S): UpgradeCode = {XXXXXX-XXXX-XXX-XXXX-XXXXXXXX} Property(S): MYKEY = [~]myvalue1[~] Property(S): MYSERVICE = myvalue2

At end of installation it seems it has correctly evaluated the MYKEY but not during AppSearch, resulting in failing my Condition evaluation

<Feature Id="MyFeature" Level="" Display="" Title="" Description="" AllowAdvertise="no" ConfigurableDirectory="INSTALLDIR">
   <MergeRef Id="MyFeature" Primary="yes"/>
   <Condition Level="0">((MsiNTProductType=1) OR 
   (MYKEY="[~]MyValue[~]") OR 
   (MYSERVICE="MyService" AND MYKEY=""))</Condition>
   </Condition>
</Feature>
<Property Id="MYKEY" Secure="yes">
        <RegistrySearch Id="MyKey"
                             Root="HKLM"
                             Key="SYSTEM\CurrentControlSet\Services\MyService"
                             Name="mykey"
                             Type="raw" />
</Property>
<Property Id="MYSERVICE" Secure="yes">
        <RegistrySearch Id="MYSERVICE"
                        Root="HKLM"
                             Key="SYSTEM\CurrentControlSet\Services\MyService"
                             Name="DisplayName"
                             Type="raw" />
</Property>

回答1:

UPDATE: I might have missed you stating it already, but when checking whether the property set by the AppSearch search has any assigned value at all using simply PROPERTYNAME as condition, the condition shows up as true - meaning that "something" exists in the property in question, the text is just not displayed.

Is it sufficient to test just for the presence of a value, or do you need to check the specific value of MYKEY? If the mere presence of a value is enough, then you may be able to use this condition:

((MsiNTProductType=1) OR (MYKEY) OR (MYSERVICE="MyService" AND MYKEY=""))


I guess this answer from Rob Mensching from the WiX-users mailing list answers the question with certainty. Multi-string is simply not supported for AppSearch.

There is no need to doubt the accuracy of this since Rob was on the original MSI team. You need to abandon this approach. Sorry to say. Unless the above workaround that I just added could work (check not the value, but if there is a value at all being retrieved from the registry).

A couple of other, potential workarounds:

  1. You could read the multi-string from a custom action. I just verified that it works with a test VBScript - the forbidden MSI tool :-).
  2. Could you search for a file or directory on disk that would signify the same thing you retrieve from the registry with this multi string?

As my motto goes every now and then: let's obsess over this (as opposed to: "careful, we don't want to learn from this" - which is another motto of mine - which tends to be the better option).

It is truly odd, that I can replicate what you state about your log file. I see a CommandLine entry which shows the multi-sting correctly, albeit with several extra null characters (slightly shortened log entry):

CommandLine: NORMALSTRING="sample regular string" MULTISTRING="[~~~]String 1[~~~]String 2[~~~]String 3[~~~]" INSTALLFOLDER="C:\Program Files (x86)\WiX3_GenericTestProject\" TARGETDIR="C:\" ACTION="INSTALL" EXECUTEACTION="INSTALL" ROOTDRIVE="C:\" INSTALLLEVEL="1" SECONDSEQUENCE="1"  ADDLOCAL=Empty,Modules,ProductFeature

and also, later in the log file, after InstallFinalize:

Property(S): MULTISTRING = [~]String 1[~]String 2[~]String 3[~]

I really don't understand how that comes about. Somehow the AppSearch must have really set the property in question even if it didn't look like it did - the property just can't be retrieved correctly (or formatted correctly), and hence doesn't work in (feature) conditions either?

Maybe the underlying data model in Windows Installer has stored the retrieved registry multi string value as a BSTR (the abomination of a COM string format which allows embedded nulls and can be compiled and linked without being properly allocated / constructed via SysAllocateString - "burnt child, smells burnt - and all that...").

Anyway, I suppose AppSearch expectes a regular, null-terminated string buffer and interprets the BSTR as such? Hence stumbling on the first null value which is the first character of the data string section of the BSTR (not the length prefix section - the BSTR pointer points 4 bytes into the allocated BSTR memory) and reports an empty string overall? The property values that show up in the log file must have been read directly from the underlying data model by other means? I would assume the MSI Win32 C++ functions? But wouldn't that also be the case for AppSearch? Something is wrong with how this property string - with embedded nulls - is being displayed and used in conditions.

So in summary: maybe the retrieval of the multi string actually works, but the exposed value via Session.Property("PROP") erroneously reads the potential, native BSTR as a null-terminated string buffer and interprets the leading null as the end of the string buffer? Sort of doesn't make sense considering Session.Property is a COM call and should definitely understand a BSTR? Theories like these are never correct, but maybe they can help create some new ideas at least. What seemed like a missing Windows Installer feature, sort of smells like a bug I think. Or as it is in the real world: a technical problem, not easily fixed and hence seen and accepted as a missing feature.


Let me link together your questions on this issue for reference (and a couple of other answers):

  • RegistryValue Element of type multiString.
  • Failing condition wix.
  • Passing multiString values to installer through command-line.