Setting conditions on MULTIPLE Components in Wix - wix

I would like to set a condition on multiple components but do not wish to reuse the condition over and over per each component but instead group the components together under a condition that's not an launch entry condition like Fragment is.
Ideas of what to use? ComponentGroup for instance was not a valid child of Directory and I don't really know what to use to group the first two components below with one condition.
PS. Fragment, DirectoryRef and Directory I'm not allowed to change.
I would like something like this:
<Fragment>
<DirectoryRef Id="blbalba">
<Directory Id="bin" Name="bin">
**<Condition>**
<my condition>
<Component Id="id1.dll" Guid="{a guid}">
<File Id="id2.dll" KeyPath="yes" Source="mysource.dll" />
</Component>
<Component Id="id3.dll" Guid="{another guid}">
<File Id="id3.dll" KeyPath="yes" Source="anothermysource.dll" />
</Component>
**</Condition>**
<Component> **bla bla bla no condition here**
</Component>
</Directory>
</DirectoryRef>
</Fragment>

You may group your components into a Feature and define single condition for this feature.
Otherwise, you must define each condition individually for each Component.
The Condition can be only set on these elements: Component, Control, Feature, Fragment, PermissionEx, Product.
https://wixtoolset.org/documentation/manual/v3/xsd/wix/condition.html

Related

Wix::heat, Is it possible to add child element under component element while harvesting?

Basically i want to add <Condition>0</Condition> element under the <Component>..</Component> element when i harvest a directory using heat.exe
I should look like below
<Component Id='JapaneseFlag' Guid='{4CB0C1EE-8370-4880-B172-CF1E9F7308F7}'>
<File Id='JaFlag' Source='.\ja.png'></File>
<Condition>INSTALLEDSWVERSION = "XYZ"</Condition>
</Component>
and i also want the conditional feature for the above component under the feature element, like
<Feature Id='JA_Flag' Title='Japanese Flag' Level='1'>
<Condition Level='0'>NOT (INSTALLEDSWVERSION = "XYZ")</Condition>
<ComponentRef Id='JapaneseFlag'/>
</Feature>
Is this possible using heat?
if not, So Is there any way to do this dynamically?
Any clue would help me to google further.
Yes, you can use xslt to transform the generated wxs file.
Check this for example.

PYRO0243 while building patch

I had the following "Reg2015" component in RTM in which I forgot to assign KeyPath:
<DirectoryRef Id="INSTALLLOCATION">
<Component Id="Reg2015" Guid="{xxx}" Win64="no" >
<RegistryKey Root="HKLM" Key="SOFTWARE\Mine" >
<RegistryValue Name="RefCount" Value="1" Type="integer" />
<RegistryValue Name="Name" Value="Mine" Type="string" Action="write" />
</RegistryKey>
</Component>
...
</DirectoryRef>
To prepare the patch, I changed "RefCount" to "2" and added to patch wxs.
Now PYRO.EXE complains like this:
error PYRO0243: Component 'Reg2015' has a changed keypath in the transform 'C:\Patch\Patch.Wixmst'. Patches cannot change the keypath of a component.
error PYRO0260: Product '{xxx}': Table 'CreateFolder' has a new row 'INSTALLLOCATION/Reg2015' added. This makes the patch not uninstallable.
I understand since there was no "KeyPath", its KeyPath defaulted to INSTALLLOCATION, but didn't know that component ID was considered as a directory.
(1) Can someone explain why?
(2) Is there any way to pass PYRO errors?
(3) For my next major release, if I add "KeyPath" to any of "RegistryValue" element, like
<RegistryValue Name="RefCount" Value="1" Type="integer" KeyPath="yes" />
should I be able to change "RefCount" to 2 in the future patch?
Thanks.
I think WiX selected Refcount as the keypath for the component - that's what the docs say. " If KeyPath is not set to 'yes' for the Component or for a child Registry value or File, WiX will look at the child elements under the Component in sequential order and try to automatically select one of them as a key path. Allowing WiX to automatically select a key path can be dangerous because adding or removing child elements under the Component can inadvertantly cause the key path to change, which can lead to installation problems. " You could verify that by looking in the MSI file with Orca to see what the Component table says about it.
So changing the keypath value probably resulted in that issue. It would be better to set another registry item (or create a new one) in the component to be the keypath.

Setting Wix icon when advertise is set to no

Seems like I'm forever asking questions about Wix.
This should be the last, and it's just a polishing one.
I'm wanting my associated files to have an icon to go with them, but in my ProgId element, the advertise is not specified which I assume defaults to no.
Therefore in the wix documentation, it states:
For an advertised ProgId, the Id of an Icon element. For a non-advertised ProgId, this is the Id of a file containing an icon resource.
I'm not understanding how this works at all. Do I set up a folder that contains the icon and reference it with IconIndex? This is the part of the .wxs I'm working with.
<Component Id ="MyApp.exe" Guid="{GUID-HERE}">
<File Id="MyApp.exe" KeyPath="yes" Source="$(var.MyApp.TargetDir)MyApp.exe" />
<ProgId Id ="MyAppProgID" Description="MyApp data files" Icon ="Logo.ico" IconIndex="0">
<Extension Id ="myapp" ContentType="application/myapp">
<Verb Id ="open" Command="open" TargetFile="MyApp.exe" Argument=""%1""/>
</Extension>
</ProgId>
<Icon Id="Logo.ico" SourceFile="$(var.MyApp.TargetDir)\Icon\Logo.ico"/>
I'm struggling to find any examples or proper documentation on a lot of the ProgId functionality for wix.
Thanks in advance
You need to change the Icon element to File and remove IconIndex
<Component Id ="MyApp.exe" Guid="{GUID-HERE}">
<File Id="MyApp.exe" KeyPath="yes" Source="$(var.MyApp.TargetDir)MyApp.exe" />
<File Id="Logo.ico" Source="$(var.MyApp.TargetDir)\Icon\Logo.ico"/>
<ProgId Id ="MyAppProgID" Description="MyApp data files" Icon ="Logo.ico">
<Extension Id ="myapp" ContentType="application/myapp">
<Verb Id ="open" Command="open" TargetFile="MyApp.exe" Argument=""%1""/>
</Extension>
</ProgId>

Wix modify an existing ini file

I was trying to modify an .ini file in Wix
If it does not exists, the msi does not complete....
how do I check for this
I really want to modify it
Yes I looked at other stackoverflow questions/answers and on google
I was trying this...
<Component Id="TestIni" Guid="*">
<CreateFolder />
<IniFile Id="Ini1"
Action="createLine"
Directory="INSTALLLOCATION"
Section="Test"
Name="Minimal.ini"
Key="TestKey"
Value="TestValue" />
<IniFile Id="Ini2"
Action="createLine"
Directory="WindowsFolder"
Section="Test"
Name="Minimal.ini"
Key="TestKey"
Value="WindowsFolder TestValue" />
</Component>
Use Action="addLine" or Action="addTag" if you want to modify an existing value.
You could use the FileSearch element to set a property and then use this property in a condition.

How to create single RegistryKey and refer to it from many RegistryValue's?

I created a RegistryKey and a RegistryValue nested inside this RegistryKey. Later I created another RegistryValue - not nested inside whatever RegistryKey in WiX's XML scheme. But I want to this second RegistryValue be inside the first RegistryKey actually after the installation complete. So I want to refer from many RegistryValue's to a single RegistryKey. How to do it?
It also requires that various registry values will be inside various components, so I can't put all the registry values inside a single registry key within the WiX scheme.
The example is presented below.
<Component>
<RegistryValue
Root="HKLM"
Name="ShortcutInstalled"
Key="SetupAndAccessoryData1"
Type="integer"
Value="1"
KeyPath="yes"
/>
</Component>
<Component>
<RegistryKey
Id="SetupAndAccessoryData1"
Action="createAndRemoveOnUninstall"
Key="SOFTWARE\$(var.Manufacturer)\$(var.ProductName)\SetupAndAccessoryData"
Root="HKLM"
>
<RegistryValue
Type="string"
Name="InstallDirectory"
Value="[ProductDirectory]"
KeyPath="yes"
>
</RegistryValue>
</RegistryKey>
</Component>
For now I must fill the Key attribute of the ShortcutInstalled RegistryValue with the same data as in the Key attribute at the RegistryKey. But I don't want to copy and paste it because of refactoring difficulties. I just want to refer to the same registry key. What is the best approach to gain it?
The RegistryKey element is mostly provided for convenience when you have many RegistryValue elements to nest under a single key. However, it is not necessary to use RegistryKey element since RegistryValue can provide the full path as well. Your example above could also be written like:
<Component>
<RegistryValue
Root="HKLM"
Key="SOFTWARE\$(var.Manufacturer)\$(var.ProductName)\SetupAndAccessoryData"
Name="ShortcutInstalled"
Value="1"
Type="integer" />
</Component>
<Component>
<RegistryValue
Id="SetupAndAccessoryData1"
Root="HKLM"
Key="SOFTWARE\$(var.Manufacturer)\$(var.ProductName)\SetupAndAccessoryData"
Name="InstallDirectory"
Value="[ProductDirectory]"
Type="string" />
</RegistryValue>
</Component>
It's mostly a matter of preference. Alternatively, if you need to refer to the same registry key in many Components then you could use a preprocessor variable to store the common part of the path, then use it across many RegistryValue elements. For example, we could modify the above to look like:
<?define CommonReg = "SOFTWARE\$(var.Manufacturer)\$(var.ProductName)\SetupAndAccessoryData" ?>
<Component>
<RegistryValue
Root="HKLM"
Key="$(var.CommonReg)"
Name="ShortcutInstalled"
Value="1"
Type="integer" />
</Component>
<Component>
<RegistryValue
Id="SetupAndAccessoryData1"
Root="HKLM"
Key="$(var.CommonReg)"
Name="InstallDirectory"
Value="[ProductDirectory]"
Type="string" />
</RegistryValue>
</Component>