How to set TARGETDIR or INSTALLDIR from a registry entry? - wix

I've got great problems setting the install dir from a value in the Windows registry which I set the last time the setup ran. This to default the path correctly. The odd thing here is that we always let the user set the installation path, even on an upgrade and if it differs from the folder of the last installation, then we don't do RemoveExistingProducts in order to let the user run several versions of the application side-by-side.
Now, I've been searching the web for a solution and I've found many suggestions but none of these actually affects my INSTALLDIR which I can see in the setup UI where I get to choose where to install.
Here's what I got at the moment:
<Property Id="PREVINSTALLDIR">
<RegistrySearch Id="PrevInstallDir"
Root="HKCU"
Key="Software\MyCompany\MyApp"
Name="InstallDir"
Type="raw" />
</Property>
<CustomAction Id="SetTargetDir" Property="TARGETDIR"
Value="[PREVINSTALLDIR]"
Execute="firstSequence" />
<InstallExecuteSequence>
<Custom Action="SetTargetDir" Before="CostFinalize"></Custom>
<RemoveExistingProducts After="InstallFinalize">PREVINSTALLDIR ~= INSTALLDIR</RemoveExistingProducts>
</InstallExecuteSequence>
Can anyone spot what I'm doing wrong here?
Note, the RemoveExistingProducts part works so PREVINSTALLDIR has been read. In the setup log I can also see this:
Action start 13:50:27: AppSearch.
AppSearch: Property: PREVINSTALLDIR, Signature: PrevInstallDir
Action ended 13:50:27: AppSearch. Return value 1.
When exiting the setup, properties are dumped into the log file and I see this:
Property(C): PREVINSTALLDIR = C:\Some\Path\MyApp
Property(C): TARGETDIR = C:\
Property(C): MyAppDir = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\MyApp\
Property(C): INSTALLDIR = C:\Program Files (x86)\MiTek\MyApp\
INSTALLDIR is not affected by my wix script above, neither is TARGETDIR which I would assume would be C:\Some\Path\MyApp as well.
I've tried a bunch of things here but regardless I just can't make TARGETDIR nor INSTALLDIR change.

This worked for me:
<!-- Existing install path -->
<Property Id="EXISTINGINSTALLDIR" Secure="yes">
<RegistrySearch Id="Locate_EXISTINGINSTALLDIR" Root="HKCU" Key="Software\$(var.CompanyName)\$(var.ProductName)" Name="InstallDir" Type="directory" />
</Property>
<!-- custom action specification -->
<CustomAction Id="Set_INSTALLDIR" Execute="firstSequence" Property="INSTALLDIR" Value="[EXISTINGINSTALLDIR]" />
<InstallExecuteSequence>
<Custom Action="Set_INSTALLDIR" After="FileCost"><![CDATA[NOT Installed AND (NOT INSTALLDIR) AND EXISTINGINSTALLDIR]]></Custom>
</InstallExecuteSequence>
<InstallUISequence>
<Custom Action="Set_INSTALLDIR" After="FileCost"><![CDATA[NOT Installed AND (NOT INSTALLDIR) AND EXISTINGINSTALLDIR]]></Custom>
</InstallUISequence>

Hi I managed to get my INSTALLLOCATION changed using this:
<SetDirectory Id="INSTALLLOCATION" Value="[$(var.PlatformProgramFilesFolder)]\[$(var.Manufacturer)]\[ProductName]" Sequence="both"></SetDirectory>
Value has to be a full path..hope this helps..:)

Related

WiX - using property within a property

I have a WiX 3.10 installer that installs an add-on module for an existing application. For this reason I use RegistrySearch to obtain the installation folder where the add-on should be put. After that an already pre-existing (meaning this is part of the base application and not the add-on) utility in the same directory must be executed with some parameters.
I tried this:
<Property Id="INSTALLFOLDER">
<RegistrySearch Id='InstallPathRegistry' Type='raw' Root='HKLM' Key='SOFTWARE\Vendor\Application' Name='InstallPath' Win64='no'/>
</Property>
<Condition Message="Application installation folder not found.">
<![CDATA[Installed OR INSTALLFOLDER]]>
</Condition>
<Property Id="WixQuietExecCmdLine" Value="RegAddOn.exe /f [INSTALLFOLDER]\Addon.RegFile" />
<CustomAction Id="QtExec" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="check" />
<InstallExecuteSequence>
<Custom Action="QtExec" OnExit="success"/>
</InstallExecuteSequence>
Unfortunately, [INSTALLFOLDER] is not resolved. Obviously, as I also get a compiler warning about this.
How can I resolve the property?
Your warning says what to do:
Warning The 'X1' Property contains '[X2]' in its value which is an illegal reference to another property. If this value is a string literal, not a property reference, please ignore this warning. To set a property with the value of another property, use a CustomAction with Property and Value attributes.
Note: use a CustomAction with Property and Value attributes.
So you need to define your property with no value
<Property Id="WixQuietExecCmdLine" Value=" " />
and use custom action to fill it
<CustomAction Id="SetProp" Property="WixQuietExecCmdLine" Value="RegAddOn.exe /f [INSTALLFOLDER]\Addon.RegFile"></CustomAction>
and run it before your current custom action
<InstallExecuteSequence>
<Custom Action="SetProp" OnExit="success"/>
<Custom Action="QtExec" After="SetProp"/>
</InstallExecuteSequence>

Cannot run default browser from WIX installation

From tutorial:
<Property Id="BROWSER">
<RegistrySearch Id='DefaultBrowser' Type='raw' Root='HKCR' Key='http\shell\open\command' />
</Property>
<CustomAction Id='LaunchBrowser' Property='BROWSER' ExeCommand='www.something.com' Return='asyncNoWait' />
<InstallExecuteSequence>
...
<Custom Action='LaunchBrowser' After='InstallFinalize'>NOT Installed</Custom>
</InstallExecuteSequence>
As I can see from installation traces, property BROWSER is calculated correctly:
Property(S): BROWSER = "C:\Program Files (x86)\Internet
Explorer\iexplore.exe" -nohome
But browser is not open after installation.
MSI (s) (88:90) [18:38:30:331]: Doing action: LaunchBrowser MSI (s)
(88:90) [18:38:30:331]: Note: 1: 2205 2: 3: ActionText Action start
18:38:30: LaunchBrowser. Action ended 18:38:30: INSTALL. Return value
1. Action ended 18:38:30: LaunchBrowser. Return value 1631.
...
MSI (c) (64:6C) [18:38:30:409]: Product: WebPrintingService -- Installation completed successfully.
What could be wrong?
Windows 7.
UAC - default.
UPDATE:
As a workaround it is possible to use following code(but I am not sure that it is a good workaround):
<Property Id="BROWSER">
<RegistrySearch Id='DefaultBrowser' Type='raw' Root='HKCR' Key='http\shell\open\command' />
</Property>
<CustomAction Id="LaunchBrowser" Directory="INSTALLDIR" Impersonate="no" Execute="deferred" ExeCommand='[BROWSER] "test.html"' Return="check"/>
<InstallExecuteSequence>
<Custom Action='LaunchBrowser' Before='InstallFinalize'>NOT Installed</Custom>
</InstallExecuteSequence>
I have not made an installer that can run the default browser after installtion but I have made an installer with WiX that launches the installed application. As far as I know, the ExeCommand property must contain the file path to an executable file. It can be either the path on your computer directly or a string property you defined containing the file path. Maybe you can tell the program wich file it should open, wich would be in your case a website.
I hope this helps.

Wix, customAction set property

I`m trying to set some launch conditions, so I just look after some registry and if they exists the installation can continue... if not it should stop...
Problem is, that it`s not working...
<Property Id="MSGEOPATHV8">
<RegistrySearch Id='msGeoV8_PathRegistry' Type='raw'
Root='HKLM' Key='SOFTWARE\Bentley\MicroStation GeoGraphics\08.01' Name='PathName' Win64='no'/>
</Property>
<CustomAction Id="caGeoPathV8" Execute="firstSequence" Property="MSGEOPATH" Value="[MSGEOPATHV8]" />
<Condition Message="[MSGEOPATH] Installation of requires previous installation of MicroStation GeoGraphics V8 or Bentley MAP XM/V8i.">MSGEOPATH</Condition>
...
...
<InstallExecuteSequence>
<Custom Action='caGeoPathV8' After='LaunchConditions' />
</InstallExecuteSequence>
I found that I need to do it after appSearch... so I checked it with orca... But custom action is scheduled after app search and before launchConditions.... so it should be ok... Also I read that probably the variable name should be upper case... something like global... so I did it and still nothing...
Any help?
Thanks
EDIT:
What I forgot to say... if I in condition mesasage replace MSGEOPATH by MSGEOPATHV8 it print actually the path what it found....
Ok, I solved it... the problem is that I don`t have defined installationUI sequence...
<InstallUISequence>
<Custom Action='caGeoPathV8' Before='LaunchConditions'>NOT Installed</Custom>
</InstallUISequence>
With this it works... but still not sure why? Because if I`m right the is executing every time or not?

Wix Toolset - Setting a Property to User Profile Folder path and Program Files

I am using Properties to set the values of Registry entries. This is so that on install the first time I have a default value and then on upgrade the current registry value is used.
I need to have a property that sets the path to the user's local folder and to the programs folder. I know the below code is wrong but how do I do it. I think at least I want to do a Type 51 custom action but don't understand the documentation.
I believe there are three relevant parts
<InstallExecuteSequence>
<Custom Action="SetUserFolder" Before="InstallInitialize"/>
<Custom Action="SetInstallFolder" Before="InstallInitialize"/>
</InstallExecuteSequence>
Custom Action
<CustomAction Id="SetUserFolder" Property="UserFolder" Value="[%USERPROFILE]" />
<CustomAction Id="SetInstallFolder" Property="P_InstallFolder" Value="[%PROGRAMFILES]" />
The property.
<Property Id="P_MyAPPPATH" Value="[P_InstallFolder]MyApp\">
<RegistrySearch Id="S_MyAppPath" Type="raw" Root="HKCU" Key="Software\MyApp\Settings" Name="MyAppPath"/>
</Property>
<Property Id="P_MyAPPDB" Value="[UserFolder]\MyApp\MyAppData\">
<RegistrySearch Id="S_MyAPPDB" Type="raw" Root="HKCU" Key="Software\MyApp\Settings" Name="MyAppdb"/>
</Property>
As an alternative to using the properties you're defining, you might be able to use some built-in properties to better effect.
Instead of %USERPROFILE, consider LocalAppDataFolder. This will avoid your data from being copied between machines as a user roams between machines on a network domain. I'm guessing you don't need that but, if you do, use AppDataFolder and beware of the latencies involved.
Instead of %PROGRAMFILES, consider ProgramFilesFolder. This seems to be what you intend.

Why isn't my Wix Property being evaluated?

I'm trying to simulate the InstallURL property of a VS.net install MSI... I've got to the ponit where the WIX MSI will open a browser to the download page that I want it to go to. I thought things were going great because on my test machine, the web page opened when I didn't have the MSXML6 component installed. However things went downhill when I discovered that the web page opened even when I DID have the component installed.
I'm searching for the MSXML6 component using a Property w/ a RegistrySearch. However, as best as I can tell, the registry value isn't even being evaluated, and thus it "always" looks like it isn't installed.
Here's the relevant portion of my WXS:
<Property Id="MSXML6">
<RegistrySearch Id="MSXML6Search" Root="HKCR" Key="Msxml2.DOMDocument.6.0" Type="raw" />
</Property>
<Property Id="TEST">
<RegistrySearch Id="TESTSearch" Root="HKLM" Type="raw" Name="Version" Key="SOFTWARE\Microsoft\DirectX" />
</Property>
<Property Id="cmd.exe" Value="cmd.exe" />
<CustomAction Id="OpenMSXML6Download" Property="cmd.exe" ExeCommand="/c start http://www.microsoft.com/downloads/details.aspx?FamilyID=993c0bcf-3bcf-4009-be21-27e85e1857b1" Execute="immediate" Return="check" />
<CustomAction Id="OpenMSXML6DownloadError" Error="This component requires MSXML6. =[MSXML6]=[cmd.exe]=[TEST]= A web browser has been opened to the download page. Please install MSXML6 and then re-install the connector." />
<!-- installation execution sequence -->
<InstallExecuteSequence>
<!-- wires the error dialog to the downgrade event -->
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
<!-- execution to delete old install info after upgrade-->
<RemoveExistingProducts After="InstallValidate" />
<!-- Forces MSXML6 to be pre-installed -->
<!-- <Custom Action="OpenMSXML6Download" Before="FindRelatedProducts">NOT MSXML6</Custom> -->
<Custom Action="OpenMSXML6Download" Before="FindRelatedProducts">NOT MSXML6</Custom>
<Custom Action="OpenMSXML6DownloadError" After="OpenMSXML6Download">NOT MSXML6</Custom>
</InstallExecuteSequence>
<!-- ui information for the custom actions above. -->
<InstallUISequence>
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
<Custom Action="OpenMSXML6Download" Before="FindRelatedProducts">NOT MSXML6</Custom>
<Custom Action="OpenMSXML6DownloadError" After="OpenMSXML6Download">NOT MSXML6</Custom>
</InstallUISequence>
What this does is if MSXML6 isn't defined then it opens the web page and then prints the custom error message. Note that I'm trying to print the value of the property in the error message (I'm not sure if this is valid or not, but it seems to be.) The text that I see says "This component requires MSXML6. ==[cmd.exe]==..." so it is printing the value of the 'cmd.exe' property but not the other two... maybe that's because I define the property explicitly, I'm not sure... Anyway, I also ran the MSI with debugging on, and in the log file, I see absolutely no reference at all to the MSXML6 or the TEST properties ever being set. I've confirmed that the registry values are indeed set, although I'm not 100% sure how to handle the Msxml2 registry key, since it doesn't have any real values, only a default value. (I'm assuming that leaving off the 'Name' parameter is the right way to handle this.)
Help??
I managed to figure this one out... it was quite a simple answer. Basic issue was that the Custom Actions were executing before AppSearch, which is where the RegistrySearch properties get evaluated. See my blog post at CTICoder for details.