I get the error "could not access network location \Common" when running the installer.
Any ideas will be much appreciated.
<Property Id="BINDIR">
<RegistrySearch Id='BinDirReg' Type='raw' Root='HKLM' Key='SOFTWARE\xxx' Name='AppDir' Win64='no'/>
</Property>
<Property Id="DATADIR">
<RegistrySearch Id='DataDirReg' Type='raw' Root='HKLM' Key='SOFTWARE\xxx' Name='DataDir' Win64='no'/>
</Property>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<UIRef Id="WixUI_InstallDir" />
<SetDirectory Id="TESTBINFOLDER" Value="[BINDIR]\a\b\c" />
<SetDirectory Id="TESTDATAFOLDER" Value="[DATADIR]\a\b\c" />
<SetDirectory Id="TESTCOMMONDATAFOLDER" Value="[DATADIR]\Common" />
The value of the DATADIR property is empty so the value of TESTCOMMONDATAFOLDER is "\Common"
You really shouldn't be trying to define your Directory structure this way since on your very first install you'll try to set the TESTCOMMONDATAFOLDER to [DATADIR]\Common but there's no way your registry key exists in the registry.
You should define your Directory Structure as a default baseline. THere are several well-definied System Folder Properties for msis that you can use to define your default directory structure.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="CompanyName">
<Directory Id="BIN" Name="_bin" />
<Directory Id="DataDir" Name="Data" />
</Directory>
</Directory>
<Directory Id="AppDataFolder" >
<Directory Id="ProductName" />
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="ProductName"/>
</Directory>
</Directory>
Define your default structure this way. If you let the user set a custom install location, you can use a registry search to set the property for the directory and everything else will update nicely. for example,
<Property Id="INSTALLDIR">
<RegistrySearch
Id="InstallDirRegSearch"
Root="HKLM"
Key="SOFTWARE\ProductName"
Name="Path"
Type="raw"/>
</Property>
And this will set the INSTALLDIR to the custom location and all the BIN and DataDir folders will get updated with the new INSTALLDIR location. You can do a similar registry search to set directory locations for all other Directories. The plus side of doing it this way is that if these registry locations do not exist, you'll still use the default defined structure for your installation.
Related
I have Wix Code which simply installs a txt file in the given location
The target location is enclosed in a Property THISONE
<Fragment>
<Property Id="THISONE" Value="C:\MyFolder"/>
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='APPLICATIONFOLDER' ComponentGuidGenerationSeed="{75266e3e-3781-47e3-ac29-46a2d90548f9}">
<Directory Id='MyFolder' Name='MyFolder'/>
</Directory>
</Directory>
<SetDirectory Id='APPLICATIONFOLDER' Value='[THISONE]' />
</Fragment>
<Fragment>
<Component Id="Component1" Directory="MyFolder" Win64="yes">
<File Id="FirstFile.txt"/>
</Component>
</Fragment>
I want a minimal UI with maybe just a textbox where I can edit the property value so that I can change the target installation file path.
How can I achieve that ?
Thanks in Advance
The WiXUIInstallDir may be what you want, as described in the WiX documentation.
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='APPLICATIONFOLDER' ComponentGuidGenerationSeed="{75266e3e-3781-47e3-ac29-46a2d90548f9}">
<Directory Id='MyFolder' Name='MyFolder'/>
</Directory>
</Directory>
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER" />
<UIRef Id="WixUI_InstallDir" />
You must set the value of the property WIXUI_INSTALLDIR to the value of the ID of the directory you want the user to be able to specify the location of, as shown above. This is then passed to the WixUI_InstallDir dialog. Note that the directory ID must all be uppercase.
If you're using Visual Studio, you'll need to add a reference to WixUIExtension to your WiX project. See here for more details.
I am struggling with Wix installer. During the install, the INSTALLDIR is overridden to a custom folder (not in Program Files). When I uninstall, the INSTALLDIR and the TARGETDIR gets set to E:\ no matter what I do.
How do I fix this? Here are the relevant snippets:
<Property Id="ARPINSTALLLOCATION">
<RegistrySearch Id="GetINSTALLDIRFromRegistry" Root="HKLM"
Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductCode]" Name="InstallLocation" Type="raw" />
</Property>
<SetDirectory Id="TARGETDIR" Value="[ARPINSTALLLOCATION]">Installed</SetDirectory>
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CreateFolders" Sequence="execute">NOT Installed</SetProperty>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLDIR" Name="WinApp">
</Directory>
</Directory>
</Fragment>
Thanks in advance. I am using Wix Tools 3.10.
Update 1
Here are my findings (for now. please correct me as I am still new to Wix)
Contrary to popular belief, the installer does not seem to set the install folders automatically during uninstall.
An important exception to the above rule is when the install folders are "well known" folders like ProgramFilesFolder.
So, If you set your directory structure to this:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLDIR">
<Directory Id="TEST" Name="WinApp" />
</Directory>
</Directory>
</Fragment>
You must set the INSTALLDIR directory through a property assignment or through a custom action. For example:
<Property Id="INSTALLDIR"><![CDATA[C:\mydir1\mydir1]]></Property>
If you set INSTALLDIR dynamically through a dialog box, you must read it from the registry or from a file (where you stored it during the install).
Update 2
Slightly improved version
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" Sequence="execute" After="InstallFiles" />
<Property Id="INSTALLDIR" Secure="yes">
<RegistrySearch Id="Locate_EXISTINGINSTALLDIR" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductCode]" Name="InstallLocation" Type="directory" />
</Property>
<CustomAction Id="SetTARGETDIR"
Directory="TARGETDIR"
Value="[INSTALLDIR]"
Return="check" />
<InstallExecuteSequence>
<!--this action launches a window to allow the user to choose the folder. don't want
to use standard MSI/Wix dialogs as the functionality is limited
-->
<Custom Action='SelectFolderCustomAction' Before='CreateFolders'>NOT Installed</Custom>
<!--<Custom Action='RegistrationInfoCustomAction' Before='InstallFinalize'>NOT Installed</Custom>-->
<!--<Custom Action='UninstallCustomAction' Before='RemoveFiles'>Installed AND REMOVE = "ALL"</Custom>-->
<Custom Action="SetTARGETDIR" Before="RemoveFiles">Installed AND REMOVE = "ALL"</Custom>
</InstallExecuteSequence>
I dont understand what you are trying to do above. Why are you reading the install location from the registry?
This is what I do for installing to "D:\Program Files" folder.
<Property Id="ROOTDRIVE"><![CDATA[D:\]]></Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles" Name="Program Files">
Remove the SetDirectory element, it's obsolete. When the product is already installed, Windows Installer automatically sets the directory properties to the pathes of the actual installation directories.
The RegistrySearch for ARPINSTALLLOCATION looks strange too. Normally this property should only be set during first install, which you already do by using the SetProperty element.
So the following should be enough:
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CreateFolders" Sequence="execute">NOT Installed</SetProperty>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLDIR" Name="WinApp"/>
</Directory>
</Fragment>
In my wix source code, I have to look for 2 entries in the registry to get an install directory :
<Property Id="INSTALLDIR_A">
<RegistrySearch Id='RegA' Type='raw'
Root='HKLM' Key='Software\Path\To\A' Name='InstallLocation' />
<Property Id="INSTALLDIR_B">
<RegistrySearch Id='RegB' Type='raw'
Root='HKLM' Key='Software\Path\To\B' Name='InstallLocation' />
My install directory must be either INSTALLDIR_A or INSTALLDIR_B. If I had to look only to 1 entry, I would have implemented it like that :
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLDIR" Name="My path">
<!-- further code -->
</Directory>
</Directory>
But I want INSTALLDIR to be either INSTALLDIR_A or INSTALLDIR_B depending on which one is defined. How to achieve this ?
There's a custom action SetDirectory (http://wixtoolset.org/documentation/manual/v3/xsd/wix/setdirectory.html) for that. You might try something like using the first value as default and overwriting it if the other one is set:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Software\Path\To\A" />
</Directory>
</Directory>
<SetDirectory Id="INSTALLFOLDER" Value="[INSTALLDIR_B]">INSTALLDIR_B AND NOT INSTALLDIR_A</SetDirectory>
</Fragment>
I'm trying to use RemoveFolderEx to delete a folder one level up from my install folder upon uninstall of the app. Here is what I have, but it's not working:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyAppBaseFolder" Name="MyAppID">
<Directory Id="INSTALLFOLDER" Name="MyAppLauncher">
<Directory Id="UPDATESCRIPTSFOLDER" Name="Scripts" />
<Component Id="CleanupMainApplicationFolder" Guid="*">
<RegistryValue Root="HKLM" Key="SOFTWARE\MyApp ID\MyApp ID Windows Client" Name="Path" Type="string" Value="${path::getfullpath(path::combine([INSTALLFOLDER],'..\MyApp'))}" KeyPath="yes" />
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
</Component>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="MyApp ID"/>
</Directory>
</Directory>
</Fragment>
The MSI will build fine, but when I run the setup it seems to be failing on the RegistryValue element and complaining about the ".." in the path. The string I'm making is like: "C:\Program Files (X86)\MyApp ID\MyAppLauncher\..\MyApp". I need it to resolve to: "C:\Program Files (X86)\MyApp ID\MyApp".
I'm not too familiar with the ${path:: ... } stuff. I saw a couple examples with ${path::combine()} so I guess I assumed that would work with getfullpath in .NET. Perhaps it does and my syntax is just wrong?
Thank you!
EDIT: Sorry, I got that ${path::combine... stuff from BUILDING WIX without fully reading what that article is doing. It has nothing to do with a wxs file, it's for NAnt (as Rob mentioned below). So I guess my question simply is this: how can I combine and resolve an absolute and relative path like C:\Program files (X86)\MyApp ID\MyAppLauncher\..\MyApp. Thanks
EDIT2: Thanks again Rob, I was focusing so much on resolving the path I didn't even consider the most obvious solution, which was to simply reference a new <Directory element. I now have it cleaning up 2 folders with the following code:
<Property Id="APPLICATIONFOLDER">
<RegistrySearch Key="SOFTWARE\MyApp ID\MyApp ID Windows Client" Root="HKLM" Type="raw" Id="APPLICATIONFOLDER_REGSEARCH" Name="Path" />
</Property>
<Property Id="PRINTERFOLDER">
<RegistrySearch Key="SOFTWARE\MyApp ID\MyApp ID Printer" Root="HKLM" Type="raw" Id="PRINTERFOLDER_REGSEARCH" Name="Path" />
</Property>
...
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyAppBaseFolder" Name="MyAppID">
<Directory Id="INSTALLFOLDER" Name="MyAppLauncher">
<Directory Id="UPDATESCRIPTSFOLDER" Name="Scripts" />
<Component Id="CleanupMainApplicationFolder" Guid="*">
<RegistryValue Root="HKLM" Key="SOFTWARE\MyApp ID\MyApp ID Windows Client" Name="Path" Type="string" Value="[LM_INSTALLFOLDER]" KeyPath="yes" />
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
<RegistryValue Root="HKLM" Key="SOFTWARE\MyApp ID\MyApp ID Printer" Name="Path" Type="string" Value="[LMP_INSTALLFOLDER]" />
<util:RemoveFolderEx On="uninstall" Property="PRINTERFOLDER" />
</Component>
</Directory>
<Directory Id="LM_INSTALLFOLDER" Name="MyApp" >
</Directory>
<Directory Id="LMP_INSTALLFOLDER" Name="MyAppPrinter" >
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="MyApp ID"/>
</Directory>
</Directory>
</Fragment>
The syntax you have in the RegistryValue/#Value looks like NAnt or something. It isn't clear what interprets that but the Windows Installer will not. You have a couple options to get that registry value correct. First, change the RegistryValue element to look like:
<RegistryValue Root="HKLM"
Key="SOFTWARE\MyApp ID\MyApp ID Windows Client"
Name="Path"
Type="string"
Value="[MyAppBaseFolder]MyApp"
KeyPath="yes" />
Alternatively, you could define "MyApp" in your Directory tree and reference it directly. That'd look a little like adding the following as a child of MyAppBaseFolder (peer of INSTALLFOLDER):
<Directory Id='MyAppFolder' Name='MyApp' />
Then updating your RegistryValue element to look like:
<RegistryValue Root="HKLM"
Key="SOFTWARE\MyApp ID\MyApp ID Windows Client"
Name="Path"
Type="string"
Value="[MyAppFolder]"
KeyPath="yes" />
I prefer the latter but that's just because I prefer using identifiers without concatenating strings.
I am creating a setup project in WiX, I've used WixUI_Common as a base and extended it with my custom dialogs. But when the user gets to the InstallDirDlg dialog, the installation path is "C:\", and this is totally unacceptable. Although previously in the code I've set:
<Directory Id="TARGETDIR" Name="SourceDir">
<Component Id="Component_SetupCM.wxs" Guid="60A58B24-CA71-44CE-947F-6BBDC7C6C89C" >
<File Source="Product.wxs" Id="Product.wxs" KeyPath="yes"/>
</Component>
</Directory>
<Property Id="WIXUI_INSTALLDIR" Value="TARGETDIR" />
So what could be the problem?
you need something like this:
<DirectoryRef Id = TARGETDIR>
<Directory Id = "ProgramFilesFolder">
<Directory Id = "INSTALLDIR" Name = "MyAppName"/>
</Directory>
</Directory>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
The problem you are have is that TARGETDIR = c:\
UPDATE:
As long as you have the line
<Property Id="WIXUI_INSTALLDIR" Value="TARGETDIR" />
You will continue to have the same problem. TARGETDIR = c:\ and it always will.
Notice in my example I set WIXUI_INSTALLDIR to INSTALLDIR and not TARGETDIR. The problem with your code was not the directory structure so much as that you were setting WIXUI_INSTALLDIR to the wrong value. My solution above works as I copied it from a project I'm currently using.