I'm making an installer with the WiX 3.5 toolset, and I've run across a problem:
The installer needs to be able to detect whether another program is present, and if so, add a DLL file in its directory. I use the following code to figure out where the second program is installed:
<Property Id="FIND_INSTALLDIR" Value="[%ProgramFilesFolder]\PROGRAM">
<RegistrySearch
Id="INSTALLDIRSearch"
Root="HKLM"
Name="UninstallString"
Type="file"
Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PROGRAM"
/>
</Property>
The trouble is, if the second program isn't installed, Windows Installer gives me an error:
Could not access network location [%ProgramFilesFolder]\PROGRAM
I need to be able to handle this gracefully, though... how do I recover from the error?
Perhaps this will help you:
Detecting the presence of a directory at install time
Basically, you need to make sure that the property you are using for the DLL folder is set to a valid path, even if the DLL will not be installed (the actual path was not found).
With Cosmin's help, I found the solution:
All I had to do is to not set Value, so that it wouldn't try to find the folder... everything else worked perfectly!
Related
CONTEXT: I created a Bootstrapper installer in order to install, if needed, the .net framework 4.8. together with the setup program I want to deliver with it.
Up to here all works nice: my program gets installed always and the .net just if needed.
The thing is that I need to add some more checks to this installer, for example check for a registry key (if another program proper version is installed) and if this does not meet the condition, then the complete installation should be aborted, nothing should be installed.
PROBLEM: the InstallCondition I have added affects just the MsiPackage but the rest of the installation seems to be considered as totally fine and installation finishes successfully, here the interesting part of code:
<util:RegistrySearch Id="OtherProgramVersionId" Root="HKLM" Key="SOFTWARE\XXX\Install::Version" Variable="OtherProgramVersion"/>
<Chain>
<PackageGroupRef Id="NetFx48Redist" />
<MsiPackage
Id="MySuperProgram.Setup"
SourceFile="$(var.MySuperProgram.Setup.TargetPath)"
InstallCondition="OtherProgramVersion >= v10.0"/>
</Chain>
As said before, even the registry key is not found or it does not fulfill the condition, the installation seems to continue "successfully" and I get it in the ControlPanel->Programs as installed... but the main .msi was not really installed! (checking the destination folder, it's empty)
QUESTION: How can I add a global condition in order to stop completely any installation at all and show the user a message with the condition not fulfilled? If possible with a standard dialog.
I have seen (and I am still experiencing) with conditions, but seems they affect just one of the items in the chain... or they seem to break the installation somehow, I have tried adding to the .msi setup creation, file Product.wxs, the condition in order to abort this installation, but when installing I get this not passed condition as a setup error, seems the exit is not clean at all... even able to see the log where I see something like this:
Error 0x80070643: Failed to install MSI package.
Thanks in advance!
If you're using WixStandardBootstrapperApplication, you can use bal:Condition to define bundle-level conditions. The WiX documentation has a sample: https://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/block_stdba_install_on_reg.html
I am using wix registry search in order to locate a plugin directory for a program I am trying to integrate with. The value of the registry key looks like this:
%PROGRAMFILES%\Product\Plugins
When I do a registry search with type="raw" like this:
<Property Id="PLUGINDIR_STRING">
<RegistrySearch Id="PluginDirSearchString"
Root="HKLM"
Key="$(var.PluginDirRegKey)"
Name="$(var.PluginDirRegKeyName)"
Type="raw"
Win64="yes" />
</Property>
I will get the exact string.
When I use type Directory like this:
<Property Id="PLUGINDIR">
<RegistrySearch Id="PluginDirSearch"
Root="HKLM"
Key="$(var.PluginDirRegKey)"
Name="$(var.PluginDirRegKeyName)"
Type="directory"
Win64="yes" />
</Property>
I will get an empty string. I am checking the values like this:
<Condition Message='plugin dir "[PLUGINDIR_STRING]" found using registry key "$(var.PluginDirRegKey)" is not a valid path, make sure the path exist'>PLUGINDIR_STRING AND NOT PLUGINDIR</Condition>
<Condition Message='Unable to find registry key "$(var.PluginDirRegKey)", make sure $(var.PRODUCT) is installed'>PLUGINDIR_STRING</Condition>
The first message is displayed indicating that PLUGINDIR_STRING is found, but not PLUGINDIR. I thought the Directory option should expand %programfiles%? How to correctly handle a registry value like this?
%PROGRAMFILES%\Product\Plugins
The raw search does not work the same as directory search. A raw search returns the values in the registry item. A directory search retrieves the value then checks to see if that registry exists - it literally is a directory search for the directory in that registry item and if it doesn't exist then it will not set the property value. The idea is that if you want to use that directory as an install location it tells you that it doesn't exist.
Anyway a verbose log should verify if this is going on - look at the AppSearch and you may find something like a 1314 error saying that the directory in that registry item does not exist.
I cannot reproduce the error you are seeing. Both raw and directory registry searches are expanding %programfiles% correctly. Everything else you are doing seems correct, so the most likely issue with your failing directory search is that your setup is a 32-bit setup and you are attempting to locate a 64-bit directory. Your AppSearch in a 32-bit install will locate the %programfiles% string in your registry entry, but it will invoke WIN64DUALFOLDERS, and search for the directory in the ProgramFiles(x86) folder. If the directory isn't there you will see an empty property value returned.
Use the well defined MSI property to get the program files location.
You can find the list of well defined properties here
So set your property to [ProgramFilesFolder]\Product\Plugins. There is also ProgramFiles64Folder but from the snippets you supplied I can't tell which one you should be using. Ideally you use a 32-bit installer to install into Program Files on a 32-bit OS and Program Files (x86) on a 64-bit OS and you would use a 64-bit installer to install into Program File on a 64-bit OS.
I am trying to configure Wix to build my msi to only perform build versions (1.0.x) of my product in conjunction with the REINSTALL property, my problem is that when I run the command line: MSIEXEC.exe /i my.msi /l*vx build-inst.log REINSTALL=ALL REINSTALLMODE=vamus it fails to do anything.
I have checked the msi log and found that it is looking for the existing product in the default folder (.\program files (x86)...\myproduct) yet when I installed it the first time I actually used a custom path (c:\myproduct). It was my impression that using REINSTALL the installer would use the installed path of the original product.
Is this actually the case? Should I be specifying the INSTALLDIR on my command line? I would rather not as this is meant for use by clients and I cannot guarantee I will know where the product was installed.
This method of performing "build" upgrades has been suggested in a couple of places but I can not find anything explaining any need to specify the INSTALLDIR
Is there any way to configure this in Wix?
Thanks
Kieran
The easiest solution would be to store the installation directory in the registry and look it up upon reinstalling.
To look up your registry value, you'd use something of the sort:
<Property Id="INSTALLDIR">
<RegistrySearch Id="InstallLocation" Root="HKCU"
Key="SOFTWARE\Company\Product" Name="Location" Type="raw" />
</Property>
If the registry value isn't found, the INSTALLDIR property will be set to your directory structure.
Rob has a complete solution on his blog for when you specify such a property from the command line.
Normally the original entries in the directory table are stored for reinstall without that you store them yourself.
So there is something "special" in your MSI, if this doesn't work. If you have a custom action which sets directory properties like INSTALLDIR, you should not use it. E.g. give them a condition "Not Installed".
I found out that the problem was due to using a wildcard for the product id, so every time a new msi was built it created a new product id.
By fixing this it seemed to resolve the problem, though I have also implemented the registry key option as it will help for upgrades where I do want to change the product id.
Thanks
I have created an installer with Visual Studio 2012 and WiX 3.7. When I try to install this on a terminal server where the local disks are hidden, I need to be able to choose a network path for installation of a file. If I choose a network disk now, I get a message box saying "Installation directory must be on a local hard drive.".
I have tried to add this line to the WiX source:
<Property Id="WIXUI_DONTVALIDATEPATH" Value="1"/>
but without any luck...
Definitely possible at least in 3.10. Add following property to your main product.wxs ...
You must TYPE IN the path you wish to install to fully.
If you try and change it change the Change Folder dialog you will get the error "installation directory must be a local hard drive"
This is a WiX bug and is scheduled to be fixed in WiX 4.0 - https://github.com/wixtoolset/issues/issues/4737
Healy
I don't think it will be possible. You need to map out the network location to make it work.
Check out FW: Issue Regarding Install on mapped/shared drives.
I created one installer with IzPack. Everything works fine. Now I'm wondering, is there a good way to create one installer that will take care of update the application if this already exists?
I tested running the installer again, but he not recognize that the application is installed.
I have used IzPack for installing and updating. IzPack does not natively tie in with any packaging system so there is no way for IzPack to conclusively know if something has been installed. You might try to interact with registry or some specific flie you create at install time but that is still messy (to me anyway).
IzPack does however check if a file already exists before overwriting it so if you are running an update then an example is that you would want binaries to be updated but user configuration left alone so do something like this inside the packs element:
<packs>
<pack name="CorePack" required="yes" preselected="yes">
<description>The core of the app.</description>
<file src="bin/binaryapp" targetdir="$INSTALL_PATH/bin"
override="true">
<os family="unix" />
</file>
<file src="etc/config.conf" targetdir="/etc/appdir">
<os family="unix" />
</file>
</pack>
</packs>
You see that the binary has override="true" where the config does not (by default override=false). Binary gets updated, config does not.
Jeff
CheckedHelloPanel will do your job, at least for windows. It writes something to the registry and checks this if you try to reinstall.