Reading DWORD values from registry using WiX's RegistrySearch - wix

I've created an installer with WiX and am trying to preserve an existing DWORD registry entry during a repair installation of my product. To store the existing values, I am using the following WiX fragment;
<Property Id="PreserveMySetting" Secure="yes">
<RegistrySearch Id="FindExistingMySetting"
Root="HKLM"
Key="Software\!(loc.ProductManufacturer)\!(loc.ProductName)"
Name="MySetting"
Type="raw"
Win64="no" />
</Property>
I then set this later on using a component driven by the saved value.
The problem is, the registry search returns the DWORD as a "Formatted" string, e.g.;
#1
Instead of just
1
This means that when my component sets the registry entry, it is created as a REG_SZ with the value "#1", even though I've indicated that it should be an integer;
<Component Id="MySettingKey"
Guid="{76C4B14C-14BC-42E1-91F0-75C9F2A20EC8}">
<RegistryValue Id="MySetting"
Action="write"
Name="MySetting"
Value="[PreserveMySetting]"
Type="integer"
KeyPath="yes"
Key="Software\!(loc.ProductManufacturer)\!(loc.ProductName)"
Root="HKMU"/>
</Component>
Is there any way to get the actual registry value for use by the component?

This is going to sound backwards, but if you change the Type attribute to string it'll work. The reason is clear when you look at your MSI's Registry table using ORCA.
When you select integer WiX author's "#[PRESERVEMYSETTING]" and when you select string it author's [PRESERVEMYSETTING]. Since PRESERVEMYSETTING is already #1 you want it to be #1 not ##1.
<Component Id="MySettingKey"
Guid="{76C4B14C-14BC-42E1-91F0-75C9F2A20EC8}">
<RegistryValue Id="MySetting"
Action="write"
Name="MySetting"
Value="[PRESERVEMYSETTING]" <!-- Secure Properties are PUBLIC properties -->
Type="string"
KeyPath="yes"
Key="Software\!(loc.ProductManufacturer)\!(loc.ProductName)"
Root="HKMU"/>
</Component>

Related

Symbole in Wix (candle.exe) error LGHT0311, windows-1252

I am trying to harvest some folders with heat,candle and light.
One of the drivers that I am harvesting have 32bits dll that have a "®" symbole inside it's description (and it's product name).
one of them :
name: mfx_mft_h264vd_32.dll ,
description : H.264 Decoder MFT for Intel® HD Graphics
During the heat.exe harvest it is able to handle it :
<Component Id="cmp9558AE64A7F57EA5334374D64EF8923F" Guid="9D4432DB-793C-4D1B-A264-C19DE7BDA0CA">
<File Id="filB8B8F8A50451F85AED239C3A3C4F0B92" KeyPath="yes" Source="$(var.SourceDirectory)\win32\mfx_mft_h264vd_32.dll">
<Class Id="{1A1703E9-3E7C-41C3-AD5A-795CBFB19552}" Context="InprocServer32" Description="H.264 Decoder MFT for Intel® HD Graphics" ThreadingModel="both" />
</File>
<RegistryValue Root="HKCR" Key="MediaFoundation\Transforms\1a1703e9-3e7c-41c3-ad5a-795cbfb19552" Value="H.264 Decoder MFT for Intel® HD Graphics" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="MediaFoundation\Transforms\1a1703e9-3e7c-41c3-ad5a-795cbfb19552" Name="InputTypes" Value="7669647300001000800000AA00389B714832363400001000800000AA00389B717669647300001000800000AA00389B714832363400001000900000AA00389B717669647300001000800000AA00389B714156433100001000800000AA00389B71" Type="binary" Action="write" />
<RegistryValue Root="HKCR" Key="MediaFoundation\Transforms\1a1703e9-3e7c-41c3-ad5a-795cbfb19552" Name="OutputTypes" Value="7669647300001000800000AA00389B714E5631326139AE42BA67FF47CCC13EED7669647300001000800000AA00389B714E56313200001000800000AA00389B71" Type="binary" Action="write" />
<RegistryValue Root="HKCR" Key="MediaFoundation\Transforms\1a1703e9-3e7c-41c3-ad5a-795cbfb19552" Name="Attributes" Value="41464D490100000015CBA788077B344A9128E64C6703C4D313000000000000000700000000000000" Type="binary" Action="write" />
<RegistryValue Root="HKCR" Key="MediaFoundation\Transforms\1a1703e9-3e7c-41c3-ad5a-795cbfb19552" Name="MFTFlags" Value="36" Type="integer" Action="write" />
<RegistryValue Root="HKCR" Key="MediaFoundation\Transforms\Categories\d6c02d4b-6833-45b4-971a-05a4b04bab91\1a1703e9-3e7c-41c3-ad5a-795cbfb19552" Value="" Type="string" Action="write" />
</Component>
The problem is when I try to use candle.exe, it return the error message:
C:\MultipackageInstaller\Developments\MultipackageInstaller\ComponentMsiOSConfig\WixTemplate\HarvestedFiles.wxs(846) : error LGHT0311 : A string was provided with characters that are not available in the specified
database code page '1252'. Either change these characters to ones that exist in the database's code page, or update the database's code page by modifying one of the following attributes: Product/#Codepage, Module/#
Codepage, Patch/#Codepage, PatchCreation/#Codepage, or WixLocalization/#Codepage.
C:\MultipackageInstaller\Developments\MultipackageInstaller\ComponentMsiOSConfig\WixTemplate\HarvestedFiles.wxs(848) : error LGHT0311 : A string was provided with characters that are not available in the specified
database code page '1252'. Either change these characters to ones that exist in the database's code page, or update the database's code page by modifying one of the following attributes: Product/#Codepage, Module/#
Codepage, Patch/#Codepage, PatchCreation/#Codepage, or WixLocalization/#Codepage.
So I looked to the code page 1252 and it seem that the "®" is handle by this encoding format.
(https://en.wikipedia.org/wiki/Windows-1252)
I tried to force the code format to wix, but no changes.
Do you have an idea why do I haves thoses messages?
Is it indeed the "®" symbole the problem?
And why it is not supported by wix either if it is in the codepage 1252?
and finaly, what solutions do I have?
Thank you to have read me until there, and I hope that someone have an idea on this
Apparently it was a problem with the visual studio cache.
I can't really explain it, but after clean my "AppData\Roaming\Microsoft\VisualStudio" folder, and rebuildt everything, I didn't have the problem anymore.

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>

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>

How to write a Feature state to a registry key

What is the best way to write, to a reg key, if a feature was installed during setup?
You should use Component with condition speified. Condition may reference feature states (current or requested - for more details see this link). I use '&' symbol - it gets requested (which should be achieved with installation) feature state.
<Component Id="MyComponentSpecificReg" Guid="YOURGUID">
<Condition>&MyFeatureId = 3</Condition> <!--install this component only of feature requested state is LOCAL (You may need other condition - please read the link I posted above)-->
<RegistryKey Root="YOUR REG ROOT" Key="YOUR REGISTRY PATH" Action="create">
<RegistryValue Name="YourKeyName" Type="string" Value="[YOUR_PROPERTY]"/>
</RegistryKey>
</Component>