Wix installer: access multiple property values - wix

If I create a property with multiple arguments like
<Property Id="MyProp" Value="Arg1=value1;Arg2=value2" />
How can I access a specific value in a CustomAction, e.g.
<CustomAction Id="MyCA" Property="MyProp" Value="[MyProp.Arg1]" />

Typically you wouldn't set the value to "Arg1=value1;Arg2=value2", you'd set the property to "value1;value2" and then tokenize the substrings around the ';' character. The custom action should know what to do with the arguments without needing to list argument names.

Related

Set File Name to Property

I have a Merge Module which installs a file. I would like to use a property passed to the Merge Module during MSI creation. Something like:
<Configuration Name='FileNameProperty'
Format='Text'
DefaultValue='[FileNameProperty]' />
<Substitution Table='CustomAction'
Row='SetFileName'
Column='Target'
Value='[=FileNameProperty]' />
<CustomAction Id='SetFileName'
Property='MYFILENAME'
Value='[MYFILENAME]' />
<InstallExecuteSequence>
<Custom Action='SetFileName'
Before='LaunchConditions'>1</Custom>
</InstallExecuteSequence>
...
<File Name="[MYFILENAME]"
Source="my-file.exe" />
Currently I am using a Custom Action, namely Type 51, which works when substituting property values for other element attributes, such as ServiceInstall DisplayName. However, in this instance the file is deployed as [MYFILENAME].
I've looked through the other Custom Actions provided by MSDN, but can't find anything that fits this situation. Any suggestions or idea if this is even possible?
My last ditch option is to include File elements for each variation of file name and select the desired file based off condition, but I would like to avoid that.
File names aren't formatted so properties can't be used. If you use multiple files, WiX's smart cabbing ensures the copies don't take up extra space in your cabinet.

How to access a property value in MSI within MSM (Merge module)

I'm currently implementing a wix(3.8) installer and the main MSI is merged with several other merge modules. I'm taking a user input during the installation and I store it in a global property called PORT like this.
In the MSI
<Property Id='PORT' Value="1">
I need to access this property value inside a condition in my merge module to edit a XML file if that condition is true. So I passed this property to the merge module as a configuration like this.
In MSI
<ConfigurationData Name="PROTOCOL" Value="[PORT]" />
In MSM
<Property Id="protocol"/>
<Configuration Name="PROTOCOL" Format="Text" DefaultValue="[protocol]"/>
<Substitution Table='CustomAction' Row='SetProtocol' Column='Target' Value='[=PROTOCOL]'/>
<CustomAction Id='SetProtocol' Property='protocol' Value='[protocol]'/>
I used the value of the property "protocol" inside my condition as below but the condition never executes.
<Condition>protocol = 1</Condition>
I tried by appending the property id with the merge module's GUID as well like this and accessing that property "NEWPORT" inside the condition. but didn't success.
<Property Id='NEWPORT' Value='[protocol.8c2910c9-5694-4312-a4cc-c9b2c2a5caa5]'/>
What would be the reason for this ? Can someone please tell me the way to access the property value in MSI within Merge module's condition element.
Thanks in advance.

Wix installer - copy attribute value to another attribute

What I want to do is copy the value of a single property, and place it as the value of another property. Is this possible with Wix?
<Property Id="PROP1" Value="default" Secure="yes"/>
I want PROP2 to have the same value some where during the UI sequence.
You can use Custom action to accomplish it. Define action as
<CustomAction Id="SetMyProperty" Execute="immediate" Property="PROP2" Value="[PROP1]" />
Then call it in <InstallUISequence> or <InstallExecuteSequence> when you need it set, something like
<Custom Action="SetMyProperty" After="FileCost"></Custom>
Although #Mischo5500 answer is correct, there is a more elegant way to achieve the same. You can use a special element, <SetProperty>, which was designed exactly for that purpose.
The benefits of using it is:
It's just one line of WiX code
It is scheduled properly by default into both sequences
The name of the element is more natural and self-explanatory
Thus, the above example can be transformed into the following:
<SetProperty Id="PROP2" Value="[PROP1]" After="FileCost" />

Custom action to set a property after a failed RegistrySearch is not running

The aim is that if the value isn't found in the registry then I want to assign a default value and then have that value display as the default value in a field in the installer UI. The default value I actually want to use is [ComputerName] but obviously I can't use [ComputerName] directly in the property value attribute because it will give me errors on compiling, specifically:
warning CNDL1077: The 'MYPROPERTY' Property contains '[ComputerName]'
in its value which is an illegal reference to another property. If
this value is a string literal, not a property reference, please
ignore this warning. To set a property with the value of another
property, use a CustomAction with Property and Value attributes.
I want to get it working with plain text before I even try [ComputerName] but so far I can't even get that working.
In my project I have a Product.wxs file which contains the Product element, lots of custom actions (most of which are running fine but they're all running significantly later) and the following elements which are not cooperating and which are all siblings under the Product element.
Property definition and registry search:
<Property Id="MYPROPERTY" Value="ADefaultValue">
<RegistrySearch Id="MyProperty" Type="raw" Root="HKLM" Win64="$(var.Win64)"
Key="Software\MyCompany\MyApplication" Name="MyProperty" />
</Property>
Custom action definition:
<CustomAction Id="SetMyPropertyDefault" Property="MYPROPERTY" Value="MyCustomValue" Execute="immediate"/>
Custom action execution:
<InstallExecuteSequence>
<Custom Action="SetMyPropertyDefault" After="AppSearch"><![CDATA[MYPROPERTY="ADefaultValue"]]></Custom>
</InstallExecuteSequence>
It just will not work for me at all.
For the custom element content I have tried:
<Custom Action="SetMyPropertyDefault" After="AppSearch"><![CDATA[MYPROPERTY="ADefaultValue"]]></Custom>
<Custom Action="SetMyPropertyDefault" After="AppSearch">1</Custom> // I thought this would always run the custom action.
<Custom Action="SetMyPropertyDefault" After="AppSearch">NOT MYPROPERTY</Custom> // Back when I wasn't using the default value on the property at all.
The result is always the same, I'm still getting "ADefaultValue" showing up in the UI, never the alternate "MyCustomValue".
According to every blog and SO post I've seen I'm doing exactly what I should be doing except clearly I'm missing something.
Any ideas?
UPDATE/Answer:
The piece of information that I was missing which was provided by #sutarmin-anton was that InstallUISequence runs before InstallExecuteSequence (seems counter-intuitive to me but there you go).
But as it happened I didn't need to explicitly duplicate the custom action call in each of the install sequence elements, instead I used the SetProperty element.
So now I've got the following in my Product.wxs as children of the Product element:
<Property Id="MYPROPERTY">
<RegistrySearch Id="MyProperty" Type="raw" Root="HKLM" Win64="$(var.Win64)" Key="Software\MyCompany\MyApplication" Name="MyProperty" />
</Property>
<SetProperty Id="MYPROPERTY" After="AppSearch" Value="[ComputerName]">NOT MYPROPERTY</SetProperty>
It now runs the SetProperty after AppSearch in both InstallUISequence and InstallExecuteSequence, but the second time it runs the NOT MYPROPERTY will come out false so it doesn't get reset, and of course if it's run in quiet mode it'll still work correctly.
When you going through installer UI, installation is in InstallUISequence. InstallExecuteSequence runs after all UI events. This is cause of you have not seen "MyCustomValue". To change your property before UI sequence you should place your custom action in "InstallUISequence".
By the way, why don't you set default value of your property to "MyCustomValue"? Then, if AppSearch wont find value in regisrty, it just leave default value that you are trying to set manually.
You may be overcomplicating things. The MYPROPERTY value will not be set at all if you don't set a default. So then you call your CA to set it if 'NOT MYPROPERTY'
I see that you've tried this, and I'd say it's the correct approach that I'd try to diagnose rather than try something else. A verbose log would be invaluable. Do a:
msiexec /i [path to msi] /l*vx [path to a text log file]
and see what CA is called, what AppSearch does, property values etc.
Your original comment of "I can't use [ComputerName] - if that's the problem why not tell us what happened and maybe there is a solution that doesn't require all this. What's the compile error, for example?

WiX Toolset - Hidden property no longer hidden when referenced elsewhere

To hide a property in WiX I'm using
<Property Id="MY_PASSWORD" Hidden="yes" />
Or
<Control Id="Password" Password="yes" Type="Edit" X="30" Y="173" Width="220" Height="18" Property="MY_PASSWORD">
What I haven't found a reliable solution for is how to keep a previously hidden password hidden in a log file after it's been evaluated in:
Another property (e.g. SetProperty, type 51 CustomAction, publish property ina dialog)
A util:XmlFile entry
Is there a way to have a password evaluated without exposing the password once it's used in another WiX element?
In the instances of SetProperty or a type 51 CustomAction, is there a way to hide the original password without needed to hide the rest of the string.
For example set Property="SOME_STRING" Value="password=[MY_PASSWORD];other=[ANOTHER_PROPERTY]", have the property string show up as "password=********;other=the evaluated string"
In the instance of using util:XmlFile, is there any way to hide a password that's evaluated here from showing up in a log file?
This is the solution I came up with, I'm open to better solutions.
In the case of (e.g. SetProperty, type 51 CustomAction, or publish property in a dialog), what I did is create a reference to the property, which I mark as Hidden="yes".
<Property Id="Property_2" Hidden="yes" />
To handle the case: For example set Property="SOME_STRING" Value="password=[MY_PASSWORD];other=[ANOTHER_PROPERTY]", have the property string show up as "password=********;other=the evaluated string"
What I did was write a type 51 CustomAction to create that new property
<CustomAction Id="Set.NewProperty" Property="NewProperty" Value="password=[MY_PASSWORD];other=[ANOTHER_PROPERTY]" />
And add a separate reference to the new property to hide it.
<Property Id="NewProperty" Hidden="yes" />
This worked for me to obscure these details from util:XmlFile.
This solution, in my opinion is less than perfect. Using this method hides the entire string. I would prefer a solution that only hides the password details portion of the string.