WIX Toolset MSI. How to read folder name from registry? - wix

This code gives me the value of the PowerShellVersion key.
<Property Id="POWERSHELLVERSION">
<RegistrySearch Id="POWERSHELLVERSION"
Type="raw"
Root="HKLM"
Key="SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine"
Name="PowerShellVersion"/>
</Property>
How can I get the name of the folder?
For example, I need to find the name of the PowerShellEngine folder in folder 3 and assign it to Property "POWERSHELLVERSION".
<Property Id="POWERSHELLVERSION">
<RegistrySearch Id="POWERSHELLVERSION"
Type="raw"
Root="HKLM"
Key="SOFTWARE\Microsoft\PowerShell\3"
Name="PowerShellEngine"/>
</Property>

This would assign the value C:\Windows\System32\WindowsPowerShell\v1.0 to POWERSHELLLOCATION.
<Property Id="POWERSHELLLOCATION">
<RegistrySearch Id="POWERSHELLVERSION"
Type="raw"
Root="HKLM"
Key="SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine"
Name="ApplicationBase"/>
</Property>

Related

Check file version from file full path

I need to check service executable version before proceed my installation.
I have read full path for registered service, from registry:
<Property Id="SOME_SERVICE_PATH">
<RegistrySearch Id="FindServicePath" Type="raw" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\TARGET_SERVICE" Name="ImagePath" />
</Property>
After that I tried to perform file search like below:
<Property Id="TARGET_SERVICE_UNSUPPORTED">
<DirectorySearch Id="ServiceParticularVersionSearch" Path="[SOME_SERVICE_PATH]">
<FileSearch Name="Service.exe" MaxVersion="2.5.0.1" />
</DirectorySearch>
</Property>
And this not ganed me results.
I suppose the problem is in the value I passed to DirectorySearch Path property.
According to the Wix documentaion Path should be initialized with
"Path on the user's system. Either absolute, or relative to containing directories"
Unfortunately, there is no place in the registry I can read service installation directory. This is 3d party component.
Are there any solutions here? important moment - Its forbidden to use custom actions in our project
As it turned out, the answer was in Type parameter of RegistrySearch element. If I assign "file" to it, I will be able to apply FileSearch on path I read and check executable version.
Another solution here is to use remark from RegistrySearch Element documentation
file
The registry value contains the path to a file. To return the full file path you must add a FileSearch element as a child of this element; otherwise, the parent directory of the file path is returned.
I mean "otherwise, the parent directory of the file path is returned"
Solution 1
<Property Id="TARGET_SERVICE_UNSUPPORTED">
<RegistrySearch Id="FindServicePath" Type="file" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\TARGET_SERVICE" Name="ImagePath" />
<FileSearch Name="Service.exe" MaxVersion="2.5.0.1" />
</DirectorySearch>
</Property>
Solution 2
<Property Id="SOME_SERVICE_PATH">
<RegistrySearch Id="FindServicePath" Type="file" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\TARGET_SERVICE" Name="ImagePath" />
</Property>
<Property Id="TARGET_SERVICE_UNSUPPORTED">
<DirectorySearch Id="ServiceParticularVersionSearch" Path="[SOME_SERVICE_PATH]">
<FileSearch Name="Service.exe" MaxVersion="2.5.0.1" />
</DirectorySearch>
</Property>

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

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.

Wix - How do I set property conditionally

I'm trying to do is:
if registrySearch exist then
set INSTALL_DIR to C:\Program Files\MyCompany\MySoftware
else
set INSTALL_DIR to C:\ProgramData\MyCompany\Folder
Anyone know to do this?
Let say this the registry key you searched.
<Property Id="REGSEARCH">
<RegistrySearch Id="TestReg"
Root="HKLM"
Key="Software\TestKey\TestKey2"
Name="Test"
Type="raw" />
</Property>
This is how to set the property conditionally.
Keep the default value as the value you need to put when the registry does not exist.
<Property Id="INSTALL_DIR" Value="C:\ProgramData\MyCompany\Folder" />
Then set the property value as follows if the registry exists.
<SetProperty Id="INSTALL_DIR" After="AppSearch" Value="C:\Program Files\MyCompany\MySoftware" Sequence="first" >
<![CDATA[REGSEARCH]]>
</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]" />