I'm trying to save the property value in registry during setup and read it next time installation is run.
I follow 'Remember property' pattern as described here
It basically works as expected, but I cannot get one scenario working:
I run setup (property gets stored in the registry)
I run setup again without entering property value on command line
I expect value of the property to be read from registry, but it is assigned default value.
I think, I know where is the problem: I have "Value" assigned to the property, while the example I've mentioned above, declares "remembered" property without "Value". In my package, I have to define the value as I use the property in UI element with RadioButtonGroup. If I don't declare Value field of the property, I get compilation error:
error LGHT0204 : ICE34: Property LOCATION (of RadioButtonGroup control LocationSelection.InstallationLocation) is not defined in the Property Table.
Can anybody give me a hint how to manage it?
Here is solution draft:
Custom actions to fill properties
<CustomAction Id='SaveCmdLineValueLocation' Property='CMDLINE_LOCATION'
Value='[LOCATION]' Execute='firstSequence' />
<CustomAction Id='SetFromCmdLineValueLocation' Property="EFFECTIVE_LOCATION"
Value='[CMDLINE_LOCATION]' Execute='firstSequence' />
<CustomAction Id='SetFromRegValueLocation' Property="EFFECTIVE_LOCATION"
Value='[REG_LOCATION]' Execute='firstSequence' />
Execute sequence that assignes EFFECTIVE_LOCATION either from registry or msiexec command line:
<InstallExecuteSequence>
<Custom Action='SaveCmdLineValueLocation' Before='AppSearch'>
LOCATION
</Custom>
<Custom Action='SetFromCmdLineValueLocation' After='AppSearch'>
CMDLINE_LOCATION
</Custom>
<Custom Action='SetFromRegValueLocation' After='AppSearch'>
REG_LOCATION AND (NOT CMDLINE_LOCATION)
</Custom>
</InstallExecuteSequence>
Properties declaration:
<!-- Property used on command-line. -->
<Property Id="LOCATION" Secure="yes">
</Property>
<!-- Property used finally with ReadioButtonGroup. It must have Value assigned (required when used with RadioButtonGroup -->
<Property Id="EFFECTIVE_LOCATION" Value="OFFICE" Secure="yes">
</Property>
<!-- Read previous value from registy (from recent installation) -->
<Property Id="REG_LOCATION" Secure="yes">
<RegistrySearch Id="loc" Root="HKLM" Key="SOFTWARE\Company\Product" Type="raw" Name="LOCATION" Win64='yes'>
</RegistrySearch>
</Property>
Related
Using Wix for the first time in 10+ years, and first time with forms/dialog entry.
Have a property defined more or less like this:
<Property Id="THE_FLAG">
<RegistrySearch Id="SearchTheFlag" Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.SimpleProductName)" Name="the_flag" Win64="$(var.Win64)" Type="raw" />
</Property>
Have a control in a form to set it:
<Control Id="TheFlagCheckBox" Type="CheckBox" X="45" Y="80" Width="220" Height="17" Property="THE_FLAG" CheckBoxValue="1" Text="Flag for something" />
At the end I want to write it:
<RegistryKey Root='HKLM' Key='SOFTWARE\$(var.Manufacturer)\$(var.SimpleProductName)' ForceCreateOnInstall='yes' >
<RegistryValue Name='the_flag' Type ='integer' Value='[THE_FLAG]' />
</RegistryKey>
If I select the checkbox, it sets the registry value. However, if I don't check the checkbox, then I get a warning when running the installer about not being able to acces the registry value. I think it is because the "value" of "THE_FLAG" is null or the empty string. I want to avoid the nasty warning to the user. I took over some code, and the previous owner used all strings for obviously DWORD values...maybe to get around the warning.
Can I set some conditionals or set the value of THE_FLAG to "0" if it is "" or null?
Add the following to your authoring:
<SetProperty Id="THE_FLAG" Value="0" Before="InstallInitialize" Sequence="execute">NOT THE_FLAG</SetProperty>
This will set the value of THE_FLAG to "0" if it's blank (in MSI, null and empty string are both blank) before the registry writes are done. A reasonable alternate value for Before is "WriteRegistryValues".
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?
I am working on a set of WiX installers that are going to share a common form. Every application needs the values set, but they are going to be different for each application.
I am trying to allow for the properties (which are linked to controls) to have a default value (or not) and to allow for the property values to be set via command line.
in my "SharedDialog.wxs" I have:
<Fragment>
<PropertyRef Id="PROP1"/>
<PropertyRef Id="PROP2"/>
<UI>
<Dialog Id="SharedDialog" Width="370" Height="270" Title="[ProductName]">
<Control Type="Edit" Id="1" Property="PROP1" Wid... Indirect="no" />
<Control Type="CheckBox" Id="2" Property="PROP2" Wid...
CheckBoxValue="1" Indirect="no"/>
</Dialog>
</Fragment>
In a file for the application specific project:
<Fragment>
<Property Id="PROP1" Value="Test"/>
<Property Id="PROP2" Value="1"/>
</Fragment>
This all works for what I am trying to do, but the problem is that when I want to clear the values as so: (so they don't have a default)
<Fragment>
<Property Id="PROP1"/>
<Property Id="PROP2"/>
</Fragment>
I get this error:
Unresolved reference to symbol 'Property:PROP1' in section 'Fragment:'.
Unresolved reference to symbol 'Property:PROP2' in section 'Fragment:'.
WiX also will not let you set value to "". The problem is that as far I can tell the checkbox will always be checked if the property has a value. How can I set the property "PROP2" to "null"?
You can undefine an existing property by setting it equal to an empty string wrapped in braces like this: PROPERTY = {} in a set property custom action. This means the property doesn't exist, it is not an empty string. See the explanation here.
For properties to be available from the command line they must be PUBLIC - they are the properties that are all UPPERCASE.
Setting PUBLIC PROPERTIES secure means they can be passed from the client to the server installation process which is required for properties that are used in deferred mode custom actions. Technically this adds them to the list of SecureCustomProperties.
You can give PUBLIC PROPERTIES a default value in the Property table, and then set other values from the command line. The command line overrides the defaults:
msiexec.exe /I "C:\Test.msi" /QN /L*V "C:\log.log" TEST="MyValue" TEST2="MyValue"
See more info:
How to set a check box to "unchecked" from the msiexec command line?
Nevermind, I found the solution:
<Fragment>
<Property Id="PROP1" Secure="yes"/>
<Property Id="PROP2" Secure="yes"/>
</Fragment>
Installer is writting SQL Server's name to registry during installing my service.
And I created a dialog window with edit control where user will type the servername . Now I want to fill this control with value from registry in ChangeMode. And if this registry key is empty to fill with some default name.
How is possible to resolve it?
I tried to put RegistrySearch node into Control node. But it seems to me it's not working..
Any help is appreciated
P.S. Looked some information here: link1. And tried code like:
<Property Id="SERVCONNSTR" Value=".\SQLEXPRESS">
</Property>
<Property Id="CONNSEARCH">
<RegistrySearch Id="servconstr" Root="HKLM"
Key="Software\$(var.Manufacturer)\SERVICE" Name="SQL Server" Type="raw"></RegistrySearch>
</Property>
<SetProperty Id="SERVCONNSTR" Value="CONNSEARCH"
After="AppSearch"><![CDATA[CONNSEARCH AND (!FEATURE1=3 OR !FEATURE2=3 OR !FEATURE3=3)]]></SetProperty>
But I'm still getting .\SQLEXPRESS in edit-control during modifying.
What i'm doing wrong?
Put RegistrySearch into a Property, and tie that property to the Control.
<Property Id="SERVCONNSTR" Value=".\SQLEXPRESS">
</Property>
<Property Id="CONNSEARCH">
<RegistrySearch Id="servconstr" Root="HKLM"
Key="Software\$(var.Manufacturer)\SERVICE" Name="SQL Server" Type="raw"></RegistrySearch>
</Property>
<SetProperty Id="SERVCONNSTR" Value="[CONNSEARCH]"
After="AppSearch">CONNSEARCH</SetProperty>
I don't know why you are using two properties, If you set your property CONNSEARCH with the registrySearch, it'll check the registry and assign it the value found there, if one is present. This happens in the AppSearch phase well before most UI's take place, where your edit box would be. So you shouldn't need to use SetProperty either.
Did you want to fill the registry key with a default value, or your property with a default value?
For the property just fill the Value attribute of the property element that is using a registry search. It'll default to that if nothing is found in registry, as I said above.
It would look like this;
<
<Property Id="CONNSEARCH" Value="DefaultValue">
<RegistrySearch Id="servconstr" Root="HKLM"
Key="Software\$(var.Manufacturer)\SERVICE" Name="SQL Server" Type="raw"></RegistrySearch>
</Property>
After Appsearch your property would be set, and if your control is tied to that property it'll be filled with that value. This will also set your default property value to "DefaultValue" If nothing is in the registry.
To create a default value for the key in the registry, I guess just put a registryKey/RegistryValue element in a component that will always be installed in this scenario, and set that key to your default value if you don't set it anywhere else.
Best
I am attempting to display the value of a property retrieved from the registry in a text edit control, with some text appended to the end of the property value. However, only the value of the property is displayed.It seems as though my custom format string is being ignored. I need to be able to assign any user modification of this text back to the property, as it will be written to the registry and read when an uninstall is performed.
Product.wxs:
<Property Id="PRIMARYDBPATH" Secure="yes">
<RegistrySearch
Id="PrimaryDbPathSearchSql"
Root="HKLM"
Key="Software\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLSERVER\Setup"
Name="SQLDataRoot"
Type="raw"
/>
<RegistrySearch
Id="PrimaryDbPathSearch"
Root="HKCU"
Key="Software\My Company\My Product"
Name="PrimaryDbPath"
Type="raw"
/>
</Property>
SetupConfigDialog.wxs:
<Control
Id="DatabasePath"
Type="Edit"
X="45" Y="139"
Width="220" Height="18"
Property="PRIMARYDBPATH"
Text="[PRIMARYDBPATH]\Data\"
/>
I'm not an expert in UI but you might consider using a SetProperty element before your Control/#Id="DatabasePath" dialog is displayed to concat the "\Data\" on the PRIMARYDBPATH Property.
Off the top of my head, something like:
<SetProperty Id="PRIMARYDBPATH" Value="[PRIMARYDBPATH]\Data\" After="AppSearch"/>