Is it possible to read from 64 and 32-bit registry entries in the same installation? - wix

In my installation I need to check presence of 64-bit entry at first.
And read its value if it is present in 64-bit part of registry.
If entry is absent then I need to try to read this entry from 32-bit registry part(Wow6432Node).
I need to read it directly from wxs file or from custom action on VBScript.
Is it possible to do?

If you're running a 64bit MSI you can set two AppSearch/RegLocator entries using the style:
<Property Id="MY_32BIT_REG">
<RegistrySearch Id="my32bitreg"
Root="HKLM"
Key="SOFTWARE\My Company"
Name="foo"
Type="raw"
Win64="no" />
</Property>
<Property Id="MY_64BIT_REG">
<RegistrySearch Id="my64bitreg"
Root="HKLM"
Key="SOFTWARE\My Company"
Name="foo"
Type="raw"
Win64="yes" />
</Property>
These entries will check the appropriate "HKLM\SOFTWARE\My Company" and "HKLM\SOFTWARE\Wow6432Node\My Company" registry hives.

Related

Create registry entry but not delete it

Working on something for Server2012 (Win8) and it's communicating with a website that uses TLS 1.2. So, for those OSes I need to add TLS 1.2 protocols since Server 2012 doesn't support on a default install. I know how to do that. I know how to not do it for a version less than Windows 10 and not doing it if it's already been enabled. The big question is:
Is there a way not using Custom Actions to create the registry entry but not delete it afterward? I'm concerned about another program maybe needing it.
For instance,
<Property Id="WIN10FOUND">
<DirectorySearch Id="searchSystem" Path="[SystemFolder]" Depth="0">
<FileSearch Id="searchFile" Name="advapi32.dll" MinVersion="6.3.10000.0"/>
</DirectorySearch>
</Property>
<Property Id="TLS12CLIENTFOUND">
<RegistrySearch Id="SearchTLS12Client" Root="HKLM" Key="SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" Name="Enabled" Type="raw"/>
</Property>
Later on in a feature,
<!-- For Server2012 add necessary registry entries to support TLS 1.2 -->
<Component Location="local" Id="Win8TLS12Registry" Guid="00000000-1111-2222-3333-123456789ABC">
<Condition><![CDATA[not WIN10FOUND and ((not TLS12CLIENTFOUND) or (TLS12CLIENTFOUND="#0"))]]></Condition>
<RegistryKey Root="HKLM" Key="SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" ForceCreateOnInstall="no">
<RegistryValue Name="DisabledByDefault" Type="integer" Value="0"/>
<RegistryValue Name="Enabled" Type="integer" Value="1"/>
</RegistryKey>
</Component>
If some other installer comes along, and at least tries to create the key and value, as it stands now, I think an uninstall will cause this to delete the key and value.
I've tested what I have, and if the key /value exists and is non-zero, then it does not create/set it and uninstall leaves it untouched. However, if it did not exist beforehand (or was 0), then the key / value are deleted.
Is there a way to create the key/value if they don't exist, but not delete on uninstall short of a Custom Action?
Sure. Make the <Component Permanent="yes".

Conditional property in wix script

I used the below property so i could avoid the add or remove option in the control panel
<Property Id="ARPSYSTEMCOMPONENT" Value="1" />
But i need to make it dynamic .I want to read the value in the registry. If a value mathes my condition i will include this orelse i wont include this line my partial code is as follows
<Property Id="NETFRAMEWORK20">
<RegistrySearch Id="NetFramework20"
Root="HKLM"
Key="Software\Microsoft\NET Framework Setup\NDP\v2.0.50727"
Name="Install"
Type="raw" />
</Property>
//Some Conditon
<Condition Message="I will create the Add or remove option since the softwar i look for s not present">
<![CDATA[Installed OR NETFRAMEWORK20]]>
</Condition>
<Property Id="ARPSYSTEMCOMPONENT" Value="1" />
//or else
Thank in Advance
Try using SetProperty. Means, instead of:
<Property Id="ARPSYSTEMCOMPONENT" Value="1" />
try:
<SetProperty Id="ARPSYSTEMCOMPONENT" After="InstallInitialize" Value="1">
<![CDATA[~~~CONDITION~~~]]>
</SetProperty>
As a side note, I would recommend first, not to hide staff you install from add/remove, and second, use standard .NET framework extension for checking if .NET framework is installed instead of inventing your own method with registry search.

Using WiX, how to skip a component when a certain registry key does not exist?

I want to copy some files into a directory in another product's installation tree, but only if that product is installed. So I figured I could set a property based on a registry search to find that product's installation root. Then I could use the property in a condition element on the component element.
Here is my code. For some reason, I am getting an error when the other product is not installed and the registry search comes up empty since the registry key will not be found.
<Property Id="PRODUCTPATH">
<RegistrySearch Id="PRODUCTPATH" Root="HKLM" Key="_MY_KEY_" Name="_MY_NAME_" Type="raw" />
</Property>
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch"/>
<Component Id="CommonDLLs" Guid="_MY_GUID_" Directory="INSTALLLOCATION">
<Condition>PRODUCTPATH</Condition>
<RegistryValue Id="_MY_ID_" Root="HKLM" Key="_MY_KEY_2" Name="Installed" Value="1" Type="integer" KeyPath="yes" />
<CopyFile Id="myfile1.dll" FileId="myfile1.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile1.dll"/>
<CopyFile Id="myfile2.dll" FileId="myfile2.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile2.dll"/>
</Component>
Try to use the util:RegistrySearch instead of RegistrySeach
This element comes with Util Extension. Check here if you don't know how to use extensions.
The util:RegistrySearch has an attribute (Result) for only checking if the key exists or not.
It would be like that:
<util:RegistrySearch
Id="PRODUCTPATH"
Variable="PRODUCTPATH"
Root="HKLM"
Key="_MY_KEY_"
Format="raw"
Result="exists">
Actually, all you have to do is add a condition to the SetProperty element like this:
<Property Id="PRODUCTPATH">
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch">PRODUCTPATH</SetProperty>

WiX - How do I get different registry keys for allusers and single user

My program will be installed to a path in registry, which has two different values for single user and all users.
So I'd like to have something like:
<Property Id="MYINSTALLDIR">
if single user, then <RegistrySearch Id='MyRegistry' Type='raw' Root='HKCU' Key='Software\MyApp\Foo' Name='InstallDir' />
else if ALLUSERS, then <RegistrySearch Id='MyRegistry' Type='raw' Root='HKLM' Key='Software\MyApp\Foo' Name='InstallDir' />
</Property>
Is this possible?
Perform the two registry searches to two different properties and then use a SetProperty custom action to assign one of the two properties to the real property based on which one has data and which one has a higher priority ( use conditions to drive the execution ).
Finally, it is working now...
With following snippet in wxs file, ALLUSER=1 or 2 can be passed to msiexec to enable HKLM registry search.
<Property Id="INSTALLDIR1">
<RegistrySearch Id='RegistryCU' Type='raw' Root='HKCU' Key='Software\Foo' Name='InstallDir' />
</Property>
<Property Id="INSTALLDIR2">
<RegistrySearch Id='RegistryLM' Type='raw' Root='HKLM' Key='Software\Foo' Name='InstallDir' />
</Property>
<CustomAction Id="PerUserInstall" Property="InstallDir" Value="[INSTALLDIR1]" Execute="immediate" />
<CustomAction Id="PerMachineInstall" Property="InstallDir" Value="[INSTALLDIR2]" Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="PerUserInstall" After="AppSearch">ALLUSERS="" OR (ALLUSERS=2 AND (NOT Privileged))</Custom>
<Custom Action="PerMachineInstall" After="AppSearch">ALLUSERS=1 OR (ALLUSERS=2 AND Privileged)</Custom>
</InstallExecuteSequence>
In my case, both HKCU and HKLM contain values and they have same priority, so the only way to do is to set property of ALLUSER in command line.

Wix CopyFile only on target machine

I need to be able to copy a file that exists on the target machines hard-drive based on a registry setting that holds the folder path.
I have been trying to get this going for a day or two and am having difficulty, can anyone help?
Thanks,
B
Try something along these lines:
<Component Id="MyComponent" Guid="E5FF53DE-1739-42c4-BE37-60F810C9CD69">
<Condition>MYTESTDIR</Condition>
<CopyFile Id="fileToCopy.datCopy" SourceName="[MYTESTDIR]fileToCopy.dat" DestinationProperty="WEBSERVICEBINFOLDER" />
</Component>
You can populate MYTESTDIR with a value from the registry using a RegistrySearch.
You can first search your registry for the file as follows:
<Property Id="PROPERTYNAME" Secure="yes">
<RegistrySearch Id="SomeID"
Root="HKLM"
Type="raw"
Key="SOFTWARE\SomeFolder\SomeSubFolder"
Win64="yes"
Name="InstallPath">
<DirectorySearch Id="REQUIREDDIRECTORY" AssignToProperty="yes" Depth="1" Path="THEEXPECTEDPATH">
</DirectorySearch>
</RegistrySearch>
</Property>
Then use a Custom Action to set the file name
<CustomAction Id="SETFILE"
Property="FILE"
Value="[PROPERTYNAME]file.extension" />
and then copy file as described by the previous answer...
<CopyFile Id="fileToCopy.datCopy" SourceName="[FILE]" DestinationProperty="[YOURDESTINATION]" />