RegistrySearch not working in Wix project - wix

I'm trying to add a check in my installer, so that if a specific registry key is not present it has to fail. That's roughly what I'm doing:
<Property Id="REGVALUE">
<RegistrySearch Id="regval" Root="HKLM" Key="SOFTWARE\Foo" Type="raw"/>
</Property>
<Condition Message="Valid Foo value not present. Found [REGVALUE]">
<![CDATA[REGVALUE = "Bar" OR REMOVE ~= "ALL"]]>
</Condition>
The problem I'm having is that this condition always fail. I tried querying different registry keys and no matter what I try, I always get a blank value. In the install log I can't see any access to the registry, nor any error related to the registry. So I'm a bit lost. Am I missing something obvious?

Found the problem. The issue was an incorrect ordering of actions in the installer ui sequence, which caused the conditions to be checked before running the registry queries.

Related

WiX toolset: Write registry key on upgrade [duplicate]

This question already has an answer here:
UPGRADINGPRODUCTCODE condition not working in wixui_install.wxs in library
(1 answer)
Closed 7 years ago.
I have an application that needs to know if it has been upgraded. So I thought of writing a registry key with the installer, which then could be read from the application. I tried to achieve this by adding the following component to the installer:
<Component Id ="Registry_IsUpgraded">
<Condition>Installed AND UPGRADINGPRODUCTCODE</Condition>
<RegistryValue Id="RegKey_IsUpgraded" Root="HKLM"
Key="SOFTWARE\Microsoft\Office\Excel\AddIns\websmsExcelAddIn"
Name="IsUpgraded" Value="yes"
Type="string" />
</Component>
However, registry key is not written during the upgrade. In the msi log I found this line:
Component: Registry_IsUpgraded; Installed: Absent; Request: Local; Action: Null
I suppose Action: Null means that the component will not be installed, since Action for other Components that are installed during the upgrade is Local.
But why is this and why is my registry key not written? Is there maybe a better/easier way to tell my application that it has been upgraded?
Installed and UPGRADINGPRODUCTCODE is always going to evaluate to false because during a major upgrade (indicated by UPGRADINGPRODUCTCODE) the new product is by definition not yet Installed.
I assume your application needs to do something on first run after each upgrade, yes? If so, just write the ProductCode property to the registry value and then in your application code trigger an event when it detects the value has changed. This will simplify your installer requirements.

WiX util:user LogonAsService failed to read attributes

I am getting an error message when running the WiX installer in console mode. It works in normal mode. The error log says
CreateUser: Error 0x80070103: failed to read attributes from custom action data
CustomAction CreateUser returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
After reading up on it appears to be something with the security of the properties Name / Account. I've tried setting the [ACCOUNT] and [PASSWORD] property to Secure="yes" but it didnt work
The log files says and the same error message:
Property(S): AdminProperties = ACCOUNT;PASSWORD
Property(S): SecureCustomProperties = ACCOUNT;NETFRAMEWORK45;PASSWORD;WIX_DOWNGRADE_DETECTED;WIX_UPGRADE_DETECTED
The command line looks something like this
C:\build\console\setup.exe -passive /Account mydomain\myuser /Password mypassword /Verify
and wix code that fails
<util:User Id="GrantUserLogOnAsService" UpdateIfExists="no" FailIfExists="no" RemoveOnUninstall ="no" CreateUser="no" LogonAsService="yes"
Name="[ACCOUNT]"/>
I also tried to hardcode it and it does succeed...
<util:User Id="GrantUserLogOnAsService" UpdateIfExists="no" FailIfExists="no" RemoveOnUninstall ="no" CreateUser="no" LogonAsService="yes"
Name="mydomain/myuser" />
I would be happy if I could just catch the error and ignore it, however the util:user does not have a vital="no" attribute. Thanks for any help on this.
The mystery is why the properties cannot be read, when [Account] = mydomain/myuser. I've verified this by looking at the logs.
Can I resolve the [ACCOUNT] property to a normal string before i pass it to util:User? since it seems to fail at resolving it inside.

WiX: Does util:User#RemoveOnUninstall support a MajorUpgrade?

As part of an WiX-based installer I have the following component with a User element (besides other components with File, ServiceInstall and ServiceControl elements):
<Component Id="cmpServiceUser" Directory="TARGETDIR" Guid="PUT-GUID-HERE">
<util:User
Id="ServiceUser"
Name="[ProductName]"
Password="[ServiceUserPassword]"
PasswordNeverExpires="yes"
LogonAsService="yes"
CreateUser="yes"
UpdateIfExists="yes"
RemoveOnUninstall="yes"
/>
</Component>
I have decided to go the only-major-upgrades way and placed the following element inside the Product:
<MajorUpgrade
Schedule="afterInstallInitialize"
DowngradeErrorMessage="A newer version of [ProductName] is already installed."
/>
The first installation of the product works as expected. During a major upgrade, I would have expected the user to be first removed (during RemoveExistingProducts) and later being created again. But it behaves different: The user is really removed nearly at the end of the installation - after the service for example has been restarted again (Process Explorer can still tell me the service's user name but not the SID any more - as the service's user was removed after the service was started).
After many hours of dissecting various installation logs I have turned to peek into the sources of the UtilExtension and probably found an explanation in scauser.cpp (slightly reformatted for better SO-readability):
// Schedule the removal because the user exists and we don't have any flags set
// that say, don't remove the user on uninstall.
//
// Note: We can't rollback the removal of a user which is why RemoveUser is a
// commit CustomAction.
So I guess this late removal of the user really belongs to the RemoveExistingProducts action in this case.
Thanks for reading this far - now the question: Is it possible to use util:User#RemoveOnUninstall in collaboration with a major upgrade strategy?

How to check an installed version of a product from MSI

After review a lot of posts in this site finally I decide to put mine.
I am preparing an MSI file with Wix.
I need to check if a particular version of an enterprise product is installed, before to install my system. I have the GUID of that product (which is the same for all versions), but I need to check if 1.10.0 version is installed.
Any idea, please.
Thanks in advance.
PD: I am newbie in Wix, so at this moment I am just using the wxs file created by default with the Setup Project.
Clarifying: I don't want to upgrade the software that I am installing, I need to check another program and version which my installer depends.
To do it properly, you probably want to use a custom action. Inside the custom action, use the MsiGetProductInfo function.
A way of doing it in pure-WiX would be to modify the example found here: How do I compare registry versions in WiX?
First create a RegistrySearch element:
<Property Id="PRODUCTVERSION">
<RegistrySearch Id="ProductVersionSearch" Root="HKLM" Key="software\Microsoft\Windows\Current Version\Uninstall\[PRODUCTCODE]" Name="DisplayVersion" Type="raw" />
</Property>
Then use a Condition element:
<Condition Message="Product version 1.10.0 must be installed">
<![CDATA[PRODUCTVERSION AND PRODUCTVERSION = "1.10.0"]]>
</Condition>
This would search for exactly version 1.10.0, so may not be what you want if you're looking for something like "v1.10.0 or newer"... But should get you started.
Perhaps try the proposed solution in this post: WiX Installer: getting version of the product being upgraded
It involves using the Upgrade table to identify the installed product, and a custom action using VBScript to determine the version.
If you want to do something like create an error message or fail the install if that version is present you can have multiple upgrade entries. Have one that has something like this, bad syntax...
<Property Id="VERSION110INSTALLED" Secure="yes" />
<Upgrade Id="YOUR_GUID">
<UpgradeVersion
Minimum="1.10.0" Maximum="1.10.0"
Property="VERSION110SINSTALLED"
IncludeMinimum="yes" IncludeMaximum="yes" OnlyDetect="yes" />
</Upgrade>
Then you have that property set if version 1.10.0 is present, and if you want to produce an error message condition it on VERSION110SINSTALLED, and sequence it after FindRelatedProducts.

WIX MajorUpgrade and return code

I am writing an installer that also contains MSI package built using WIX. I check the return code after running msiexec and skip some error codes. For example user should't receive error when return code is 1638 (product has already installed)
But when the older version of product was installed the return code is 1603 (unknown error). I also want to skip this situation (user already get newer version)
Wix code is
<Upgrade Id="<GUID>">
<UpgradeVersion Minimum="$(var.product_version)" OnlyDetect="yes" Property="NEWERFOUND" />
<UpgradeVersion Minimum="0.1.0" IncludeMinimum="yes" Maximum="$(var.product_version)" IncludeMaximum="no" Property="SELFFOUND" />
</Upgrade>
<MajorUpgrade DowngradeErrorMessage=You have installed newer version $(var.product_name)." />
The question is how I can return another code than 1603 when SELFFOUND or NEWERFOUND properties are activated
Update: I didn't want to influence the return code, I want to get appropriate code instead the general fatal error
You can't control the return code of msiexec.exe. Its return codes are documented and the list is comprehensive. The service determines the exit code based on the status of installation.
Update: The only thing I can suggest is to use database functions directly:
MsiOpenPackage, and
MsiDoAction("FindRelatedProducts") to run FindRelatedProducts action which will evaluate SELFFOUND and NEWERFOUND properties by processing Upgrade table.
Then analyze the properties with MsiGetProperty.
Close the package with MsiCloseHandle.
Using the obtained values of SELFFOUND and NEWERFOUND, you can decide whether you need to install the product or not. If yes, you can run msiexec.exe or use MsiInstallProduct.
Disclamer: I have never tried to do anything like this, and I am not sure it will work. It should, yet it does not look easy.