Wix is not allowed the user to override the directory - wix

I am using customized UI which works in a flow of different views like installview, progressview, finishview, uninstallview etc. In the custom installer there is two options, One is to change the install directory and other to change the database directory. My custom installer contains two msi. whenever I tried to pass the database directory to the msi it will not overide. It always taking the default path.
my custom installer contains a variable for database which is overidable, and passing the value to the msi.
<Variable Name="DatabaseFolder" bal:Overridable="yes" Type="string" Value="[CommonAppDataFolder]$(var.ManufacturerName)\$(var.ProductName)" />
<MsiPackage Id="StorageApp"
DisplayInternalUI="no"
DisplayName="$(var.StorageApp)"
Permanent="no"
Visible="yes"
Vital="yes"
SourceFile="$(var.StorageAppExe)"
Compressed="yes">
<MsiProperty Name="DATABASEAPPDATAFOLDER" Value="[DatabaseFolder]" />
</MsiPackage>
By default it takes the DatabaseProductName as the directory name. But if i changed the directory it always taking the default path. Why i couldn't overide the default value. Is there anything missing in my code?
<DirectoryRef Id="TARGETDIR">
<Directory Id="CommonAppDataFolder">
<Directory Id="CompanyAppDataFolder" Name="$(var.DatabaseManufacturerName)">
<Directory Id="DATABASEAPPDATAFOLDER" Name="$(var.DatabaseProductName)">
</Directory>
</Directory>
</Directory>
</DirectoryRef>

Not sure what you mean with "But if I changed the directory...". Did you change the value of $(var.DatabaseProductName) or just the Directory Id?
Make sure you verify your directory structure by setting a directory name directly in the "Name=" attribute instead of passing a value through $(var.DatabaseProductName)
Example:
<DirectoryRef Id="TARGETDIR">
<Directory Id="CommonAppDataFolder">
<Directory Id="CompanyAppDataFolder" Name="Folder1">
<Directory Id="DATABASEAPPDATAFOLDER" Name="SubFolder1">
</Directory>
</Directory>
</Directory>
</DirectoryRef>
Just a reminder. The Directory Id is just for you to reference your folder elsewhere in your .wxs file. The string that you fill in for the "Name=" attribute will be the actual name of your folder when you ultimately install your application.

Related

How to set Wix Property from UI which user can change during installation?

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.

How do I remove files and Folders from ProgramData Folder on Uninstall

Hi there I am having a problem getting my Wix installer to remove elements on Uninstall. The problem folders and files are located on our corporate specified programdata folder 'D:\programdata'. The folders get created OK, however will not remove on Uninstall. The folder structure is as follows
D:\programdata
Company Name
App Name
Logs
QueryOutput
The following is an excerpt from the relevant section of the product.wxs file:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="CommonAppDataFolder" Name="CommonAppData" >
<Directory Id="dirCompanyAppData" Name="Company Name">
<Directory Id="dirAppNameAppData" Name="AppName">
<Component Id="cmpDirCommonAppData" Guid="{F808944A-D898-43F3-BA1D-A35A3FD7DF41}" KeyPath="yes">
<CreateFolder Directory="dirAppNameAppData" />
<RemoveFile Id="PurgeAppName" Name="*.*" On="uninstall" />
<RemoveFolder Id="idDirAppNameAppData" On="uninstall" Directory="dirAppNameAppData" />
</Component>
</Directory>
<Component Id="cmpDirCompanyName" Guid="{A1E7E75A-D582-40C5-BD6B-D36BFB11795E}" KeyPath="yes">
<RemoveFile Id="PurgeCompanyName" Name="*.*" On="uninstall" />
<RemoveFolder Id="idDirCompanName" On="uninstall" Directory="dirCompanyNameAppData" />
</Component>
</Directory>
</Directory>
<Directory Id="ProgramFilesFolder">
... etc
Note company and application identifying elements have been replaced in the code. I have left out the remainder of the wxs file for brevity and because I believe the relevent code is included in this extract. Any assistance much appreciated, this has me stumped.
Kind Regards
Paul J.
From RemoveFolder definition:
Remove an empty folder if the parent component is selected for installation or removal.
In your case the AppData folder probably has user specific configuration in it like it is supposed to.
I think all the component planning is done first, then executed. So, RemoveFile will plan all the files in that folder to be removed and RemoveFolder will decide it shouldn't delete the folder because at the time of planning, the folder still has stuff in it that is not part of the installation included components and therefore not empty.
You will need to use util:RemoveFolderEx. Again there is another caveat to using this.
Because it might dramatically affect Windows Installer's File Costing, the temporary rows must be written before the CostInitialize standard action. Unfortunately, MSI doesn't create properties for the Directory hierarchy in your package until later, in the CostFinalize action.
So you need to manually set a directory based off of a property you probably read from the registry before the WixRemoveFoldersEx action which I think is scheduled just before CostInitialize.

WiX: FileSource confusion

Just trying to setup an installer for the first time, bit confusing.
This code;
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="FTSM" Name="FTSM">
<Directory Id="INSTALLFOLDER" Name="FCP" FileSource="..\FCP\bin\Debug\">
<Component Id="MainExecutable">
<File Id="FCPEXE" Name="FCP.exe" Source="FCP.exe" KeyPath="yes"/>
<Shortcut Id="startMenuFCP" Directory="ProgramMenuDir" Name="FCP" WorkingDirectory="INSTALLDIR" Icon="FCP.exe" IconIndex="0" Advertise="yes"/>
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
Doesn't give me any success, I always get System cannot find the file 'FCP.exe'
If I take the FileSource variable and put it into the source variable, like so;
<File Id="FCPEXE" Name="FCP.exe" Source="..\FCP\bin\Debug\FCP.exe" KeyPath="yes"/>
Then everything works perfectly. I can build the WiX project without errors and it generates an installer that works as expected.
The file structure is as follows;
Main
-> FCP (Main Project)
--> bin
---> Debug
----> FCP.exe
-> Installer (WiX Project)
--> Product.wxs
Obviously not a big issue for this Project, but when I run into multiple components, it's going to be a lot handier to specify the FileSource once.
From Bob Arnson's blog-entry Choosing your payloads:
When you use the File/#Name attribute and don’t use the File/#Source
attribute, the compiler constructs an implicit path to the file based
on the file’s parent component directory plus the name you supply.
Thus when File/#Source is present WiX will use it regardless of any Directory/#FileSource, if it is not then the source path is constructed by combining Directory/#FileSource and File/#Name.
So, a bit of a lucky find really, but it turns out if you use the references folder from within the WiX project you can then do some neat referencing in the wxs file.
I referenced my project and could then do the following;
<File Id="FCPEXE" Name="FCP.exe" Source="$(var.FCP.TargetDir)\FCP.exe" KeyPath="yes"/>

Wix - Setting Install Folder correctly

I'm creating a program which is being installed by Wix, using VS 2010 and I've already got the product.wxs ready.
In my wxs file, I've got directory definitions which looks like this:
<SetDirectory Id="INSTALLFOLDER" Value="[WindowsVolume]Myapp" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDER" Name="Myapp">
<Directory Id="Myapp_Installer_Dir" Name="Myapp">
<Directory Id="BIN" Name="Bin" />
<Directory Id="ICONS" Name="Icons" />
</Directory>
</Directory>
</Directory>
And then I got these file installation definitions:
<DirectoryRef Id="Myapp_Installer_Dir">
<Component Id="INSTALLER_Myapp" Guid="{94F18477-8562-4004-BC6F-5629CC19E4CB}" >
<File Source="$(var.Myapp.TargetPath)" KeyPath="yes"/>
</Component>
</DirectoryRef>
<DirectoryRef Id="BIN">
<Component Id="INSTALLER_Data" Guid="{545FB5DD-8A52-44D7-898E-7316E70A93F5}" >
<File Source="$(var.Data.TargetPath)" KeyPath="yes"/>
</Component>
...
And it continues in that manner. The files for the "ICONS" directory are defined as well.
I am also using the WixUI_InstallDir dialog set and I got these lines present as well:
<Property Id="WIXUI_INSTALLDIR" Value="Myapp_Installer_Dir" />
<UIRef Id="WixUI_InstallDir" />
The problem is when the user installs the program and changes the value of the installation folder, the files of the "Bin" and "Icons" are installed to their correct path, but the Myapp target is installed to a fix location which was defined at the start as the default installation path.
Why do only the bin and icon files installed to the correct folder the user wanted, but the myapp target does not?
I have finally figured out the problem.
After searching for a while, I came across this document:
WixUI_InstallDir Dialog Set
The relevant part: "The directory ID must be all uppercase characters because it must be passed from the UI to the execute sequence to take effect."
And as you can see in my code: "Myapp_Installer_Dir" does not meet this criteria.
After changing it to "MYAPPINSTALLERDIR", everything worked.
I'm not quite sure, but this is what I think has happened.
When you author a SetDirectory element, you basically add a custom action which sets a directory to the MSI database. As long as you do not specify the sequence it is executed in, it defaults to both, which means execute in both InstallUISequence and InstallExecuteSequence.
Now, when a user changes the installation directory in the wizard, this happens in the UI sequence. Obviously, when the installation enters the execute sequence, the value of INSTALLFOLDER is set to [WindowsVolume]Myapp as it was instructed.
So, you have to rework this somehow. Keep in mind the silent installation as well - there's only execute sequence there.
UPDATE instead of what you have, try something like this:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="WindowsVolume">
<Directory Id="INSTALLFOLDER" Name="Myapp">
<Directory Id="BIN" Name="Bin" />
<Directory Id="ICONS" Name="Icons" />
</Directory>
</Directory>
</Directory>
And let the user optionally change the INSTALLFOLDER as you do now.
Additionally to the pitfall with capital letters there is also an other one:
You have to mark the ID of the changeable directory as secure. (At least when the setup runs with admin rights.)
Related to Yonatan's answer with the directory ID MYAPPINSTALLERDIR you have to add this:
<Property Id="MYAPPINSTALLERDIR" Secure="yes" />
Related to the example WixUI_InstallDir in the WiX documentation you have to add this:
<Property Id="TESTFILEPRODUCTDIR" Secure="yes" />
Unfortunately this important fact is not mentioned in the WiX example.

"ICE38: Component installs to user profile" error for a specific component

I am trying to write a Windows Installer script in WiX 3.6 with a per-machine and x64 architecture only setting. I have the following project structure (shortened):
<Directory Id="ProgramFiles64Folder" Name="PFiles">
<Directory Id="APPLICATIONFOLDER" Name="My Company">
<Directory Id="ProductFolder" Name="My Product">
<Component Id="MainComponent" Guid="" Win64="yes" KeyPath="yes">
...
</Component>
<Directory Id="DataFolder" Name="Data">
<Directory Id="Machine" Name="Machine" >
<Directory Id="MachinesFolder" Name="Machines">
<Component Id="Machine1" Guid="{74341536-72DF-48C3-95E8-2851D9FA8318}" Win64="yes" KeyPath="yes">
...
</Component>
</Directory>
<Directory Id="TemplateFolder" Name="Template">
<Component Id="TemplateFiles" Guid="{A0D0C225-D604-4B84-971D-41687A30EC36}" Win64="yes" KeyPath="yes">
<File Id="Template1.rsbak" Source="$(var.SolutionDir)bin\Release\File1.rsbak" />
...
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
The problem is that I receive the error ICE38: Component TemplateFiles installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file for the TemplateFiles component when I compile. What confuses me is that I use a similar structure in another project (working), and have several components with the exact same setup in my project (not shown above). Why does this - and this only - component insist on installing to the user profile when all others get installed correctly, to Program Files?
Looks like there's significant difference for msi between Program Files and Users\UserName\Documents folders. The last is referenced in your example:
<Directory Id="DataFolder" Name="Data">
I came to the similar problem and found an answer in the blog post - https://robmensching.com/blog/posts/2007/4/27/how-to-create-an-uninstall-shortcut-and-pass-all-the/
In short you need to define RegistryKey on HKCU root as subelement to Component and add RemoveFolder element as subelement to Directory. See the link above for full example. In addition:
Remove KeyPath attribute from Component element
RemoveFolder possibly have to be defined for all folders. I used dummy component with no file inside for that