I'm using Wix Toolset for my installation package. I want the user to select the installation path and install my application to that directory but I'm unable to do that. I've tried a few things but they did not worked out. I'll share some of my wix project code and write what I tried. First my code :
<wix>
<Property Id="WIXUI_INSTALLDIR" Value="APPROOTFOLDER" />
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
</wix>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="APPROOTFOLDER" Name="MyApp">
.
.
.
<SetDirectory Id="APPROOTFOLDER" Value="[WindowsVolume]MyApp\[ProductName]"/>
</Fragment>
I dont share the whole project because I think the rest is not relevant to this part. Right now with this setup I can show to user C:\MyApp\test as default path and user can change that by clicking browse. but since I set the directory with <SetDirectory Id="APPROOTFOLDER" Value="[WindowsVolume]MyApp\[ProductName]"/> this line, when the user change the path the installer is still using C:\MyApp\test. I tried to remove that line and it worked, I was able to install where ever I browse but then the installer pick a random default path. Basically I just want to provide a default path as [WindowsVolume]MyApp[ProductName] and also let the user to change that path and install to that path.
How can I achieve that?
I found the solution, I'll write it down instead of deleting the question maybe someone will be in the situation I am right now.
I've changed the
<Property Id="WIXUI_INSTALLDIR" Value="APPROOTFOLDER" />
line with
<Property Id="WIXUI_INSTALLDIR" Value="TARGETDIR" />
and instead of setting the directory of APPROOTFOLDER I set TARGETDIR.
so instead of this :
<SetDirectory Id="APPROOTFOLDER" Value="[WindowsVolume]MyApp\[ProductName]"/>
I did this:
<SetDirectory Id="TARGETDIR" Value="[WindowsVolume]MyApp\[ProductName]"/>
I'm not 100% sure what was the problem here tbh, I think the problem was I was not using my root directory Id both in WIXUI_INSTALLDIR property and SetDirectory, I was using a sub directory in my root so probably that was the problem. So if you face a similar problem like this be sure you work with your root..
Related
WiX newbie here. I'm curious if this approach is possible using WiX.
Problem statement...
I am packaging some SQL files that I want to execute against some parameters that the user will enter at run time. Think connection string information. One of the parameters that the user can enter is the directory where they want the DB to be installed.
Current solution (doesn't work).....
To do this i'm packaging these files using heat. When it sucks in this files one of my SQL files has some tokens in them that a custom action looks for to basically do a find replace in the file. The problem is thatwhile it is indeed doing a find replace it's doing them against the source files that heat sucked in and not the files that exist in the .msi file.
Question 1...
Within the WiX workflow is there a way that via a custom action I can do processing on the files that are stored within the .cab or .msi file? If that is possible can someone show me an example of this?
Question 2 . . .
If question 1 isn't possible the other idea I had was to break the find replace SQL piece and the file install piece into separate msi file. So the first step would be to explode all the files I need into the install directory via one msi. The next msi would execute the SQL piece as at that point the files exist on the file system for me to do editing on. Does this sound like a sane approach to the problem? It could very well be that I'm trying to work around WiX and not with WiX here.
Current code snippets
<Product>
<!-- This is where this will be installed-->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDER" Name="ZOLLData">
<Directory Id="SQLINSTALLFOLDER" Name="Sql" />
</Directory>
</Directory>
<!-- CUSTOM ACTION DEFINITIONS-->
<CustomAction Id="FindReplaceZEDSTextCA"
Return="check"
BinaryKey="GemstoneInPremiseInstallerCustomActions.CA.dll"
Execute="immediate"
DllEntry="FindReplaceText" />
<!-- Database Information-->
<util:User Id="SQLUser" Name="[SQLUSERNAME]" Password="[SQLPASSWORD]"/>
<sql:SqlDatabase Id="MasterDatabase" Database="master"
Server="[SQLSERVERNAME]"
User="SQLUser"/>
<InstallUISequence>
<Show Dialog="SqlConnectionDlg" After="CostFinalize" />
<Show Dialog="ProgressDlgCustom" After="SqlConnectionDlg"/>
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="FindReplaceZEDSTextCA" After="InstallFiles">
</Custom>
</InstallExecuteSequence>
</Product>
<Fragment>
<DirectoryRef Id="INSTALLFOLDER" />
</Fragment>
<Fragment>
<ComponentGroup Id="SqlComponents">
<Component Id="CreateDatabase.sql" Directory="INSTALLFOLDER" Guid="6A2C6088-9302-451C-A01B-02D618D4AC27">
</Component>
</ComponentGroup>
</Fragment>
Thanks in advance.
The problem was the my custom action was set with Execute="immediate". This should have been Execute="deferred".
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.
I've been using Wix 3.5 with WixVSExtension to install project item templates for Visual Studio 2010, Visual C# 2010 Express and Visual Web Developer 2010 Express. I'd like now to add support for Visual Studio 11 Beta.
I added registry search and custom actions to find the VS11 installation folders but, when specifying directory and components structure, I'm getting compilation errors like this one:
error LGHT0204: ICE30: The target file 'ewa5nwrn.zip|BasicApplication.zip' is installed in '[TARGETDIR]\CSharp\' by two different components on an LFN system: 'VS2010CSharpProjectTemplates' and 'VS11CSharpProjectTemplates'. This breaks component reference counting.
I have this directory structure:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="VS2010_PROJECTTEMPLATES_DIR">
<Directory Id="VS2010_PROJECTTEMPLATES_CSHARP_DIR" Name="CSharp">
</Directory>
</Directory>
<Directory Id="VS11_PROJECTTEMPLATES_DIR">
<Directory Id="VS11_PROJECTTEMPLATES_CSHARP_DIR" Name="CSharp">
</Directory>
</Directory>
</Directory>
Notice that I have VS2010_PROJECTTEMPLATES_DIR and VS11_PROJECTTEMPLATES_DIR inside TARGETDIR. The error message shows that they are ignored.
The components are defined as follow:
<DirectoryRef Id="VS2010_PROJECTTEMPLATES_CSHARP_DIR">
<Component Id="VS2010CSharpProjectTemplates" Guid="{0976A222-8243-40F2-81AB-84D8F1771840}" Transitive="yes">
<File Id="VS2010BasicApplication" Source="BasicApplication.zip" />
</Component>
</DirectoryRef>
<DirectoryRef Id="VS11_PROJECTTEMPLATES_CSHARP_DIR">
<Component Id="VS11CSharpProjectTemplates" Guid="{A70428F1-AE26-4B07-9F58-D67587B44657}" Transitive="yes">
<File Id="VS11BasicApplication" Source="BasicApplication.zip" />
</Component>
</DirectoryRef>
Is it possible to install the same file into two different directories specified by properties?
Thanks in advance,
aalmada
I don't have any source code to share but I can tell you in general how I've done this in the past.
We decided to "install" the zip files to our main application directory in a Integration folder so that the files would always be available even if VS2008 and/or VS2010 had not been installed at the time of installation. I then used a bunch of built-in properties that exist in the Util extension and a couple custom RegLocator searches to define a bunch of properties related to the location of devenv.exe and ItemTemplate, ProjectTemplates and other directories that we needed in .NET. I then used those properties in CopyFile elements so that MSI would duplicate those files in the Integration folder to the actual VS directories as needed and approriate. Finally I used the WiX QuietExec custom action to call Devenv /setup to register the content with VS. I also used the ProgressText element ( ActionText table ) to make the UI look good while this was all happening as VS devenv can take awhile.
As explained in the wix documentation of the Directory element: when you omit the Name attribute you are creating an alias for the parent Directory element.
This is done by recording "." as the directory name in the installer database, as explained in the windows installer documentation for the Directory table.
In your case, I believe you attempt to change this "." value into a real directory name by setting the VS2010_PROJECTTEMPLATES_DIR and VS11_PROJECTTEMPLATES_DIR properties (because directories are properties) during the installation.
That's fine, but the problem here is that the light linker doesn't know what values you will set these properties to during the installation. It only has the Name attribute value to work with. And at link time, it looks like you are installing the same file twice to the same directory.
To fix this, add Name attributes with different placeholder values to the VS2010_PROJECTTEMPLATES_DIR and VS11_PROJECTTEMPLATES_DIR directory elements.
I ended up adding two base directories, under TARGETDIR, with the Name properties set:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="VS2010" Name="VS2010">
<Directory Id="VS2010_PROJECTTEMPLATES_DIR">
<Directory Id="VS2010_PROJECTTEMPLATES_CSHARP_DIR" Name="CSharp">
</Directory>
</Directory>
</Directory>
<Directory Id="VS11" Name="VS11">
<Directory Id="VS11_PROJECTTEMPLATES_DIR">
<Directory Id="VS11_PROJECTTEMPLATES_CSHARP_DIR" Name="CSharp">
</Directory>
</Directory>
</Directory>
</Directory>
Here is the code for the properties (based on the WixVSExtension code):
<Property Id="VS11DEVENV" Secure="yes">
<RegistrySearch Id="VS11DevEnvSearch" Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VS" Name="EnvironmentPath" Type="raw"/>
</Property>
<Property Id="VS11_ROOT_FOLDER" Secure="yes">
<RegistrySearch Id="SearchForVS11RootPath" Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\SxS\VS7" Name="11.0" Type="raw"/>
</Property>
<Property Id="VS11_PROJECTTEMPLATES_DIR" Secure="yes">
<RegistrySearch Id="VS11DevEnvForProjectTemplatesSearch" Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VS" Name="EnvironmentDirectory" Type="raw">
<DirectorySearch Id="VS11ProjectTemplatesPathSearch" Path="ProjectTemplates" Depth="1" />
</RegistrySearch>
</Property>
<Property Id="VS11_ITEMTEMPLATES_DIR" Secure="yes">
<RegistrySearch Id="VS11DevEnvForItemTemplatesSearch" Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VS" Name="EnvironmentDirectory" Type="raw">
<DirectorySearch Id="VS11ItemTemplatesPathSearch" Path="ItemTemplates" Depth="1" />
</RegistrySearch>
</Property>
<CustomAction Id="VS11InstallVSTemplates" Property="VS11DEVENV" ExeCommand="/InstallVSTemplates" Execute="deferred" Return="ignore" Impersonate="no" />
I then found out that the VS2010 templates don't expand correctly under VS11 but that's a different question now... :-/
I need to install my app's files to usual location like C:\Program Files\MyApp
and also need to copy several of them into custom folder in another partition
(let's say D:\CustomFolder, it's allowed to hardcode it).
Install should be silent - no gui or wizard. And alose everything should be in one *.msi file.
I can do that via CustomActions, but elegant-declarative way is preferable.
Has anyone tried this before?
Thanks.
UPDATE:
Forgot to mention, that it's allowed for files that should be on separate partition to be in C:\Program Files\MyApp
Solved. The approach is:
Specify custom folder where file should be put:
<Property Id="MY_CUSTOM_DESTINATION" Value="D:\MyCustomFolder" />
Put <Copy ..> directive into <File ...> which should be copied
<DirectoryRef Id="MyAppFolderThatIsInProgramFiles">
<Component Id="MyComponent" Guid="some_guid">
<File Id="MyFileXml" Source="MyFile.xml" KeyPath="yes" >
<CopyFile Id="Copy_MyFileXml" DestinationProperty="MY_CUSTOM_DESTINATION"/>
</File>
</Component>
</DirectoryRef>
p.s. as a side-effect, file specified in <File Id="MyFileXml" ... /> will be put into both location: C:\Program Files\MyApp and D:\MyCustomFolder, but that's correct for my task.
It's against Windows Installer Best Practices to hard code directories. You can never assume there will always be a D: or even a C:. Still, customers have asked (demanded) that I install something to D:\FOO.
So, how to make the customer happy and have the install still "work" on that VM that doesn't have a D:? By redirecting the directory at install time with a custom action that only redirects it if D: is a fixed hard disk.
Also, while the CopyFile element is useful, it's not really needed because you can just author the files into components twice and smart cabing will make sure your MSI doesn't bloat up by having the File records point to the same entry in media \ cab storage.
You can simply describe your disk structure under the Directory Tag:
<Property Id="DRIVE_1" Value="c:\" />
<Property Id="DRIVE_2" Value="d:\" />
<Property Id="DRIVE_3" Value="e:\" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="DRIVE_1" />
<Directory Id="DRIVE_2" />
<Directory Id="DRIVE_3" />
</Directory>
I wouldn't advocate hardcoding, but you get the idea.
I want the installer to skip showing setup type screen (where you can choose Typical, Custom, Complete features), How can I do this?
I provided only one feature set named product.
And I also want the user be able to change the installation directory.
If you only require the user to customize the installation folder, use:
<UIRef Id="WixUI_InstallDir" />
If you don't permit customization of the installation folder, use:
<UIRef Id="WixUI_Minimal" />
Chances are you're using one of the built in libraries that does include the Feature Tree selction, i.e.
WixUI_Mondo
WixUI_FeatureTree
WixUI_Advanced
My application only has a licence screen then installation directory screen, and I use this configuration block to-do it:
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
<UIRef Id="WixUI_InstallDir" />
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
just before the end of my </Product> tag. All the application installs into INSTALLLOCATION in the <Directory> section.
The WixUI dialog library guide might help explain the options