How to use WixToolset DirectorySearch - wix

I've been struggling with the DirectorySearch command.
I want to find the Templates folder that is located under the Microsoft Office folder.
It can be in either of the following two locations:
Microsoft Office\Templates
Microsoft Office\Root\Templates
I've tried the following
....
<Directory Id="MICROSOFTOFFICE" Name="Microsoft Office">
<Directory Id="TEMPLATES"/>
</Directory>
<Property Id="TEMPLATES">
<DirectorySearch Id='MSDir' Path='[MICROSOFTOFFICE]' >
<DirectorySearch Id='TDir' Depth='3' Path='Templates'/>
</DirectorySearch>
</Property>
What am I doing wrong?
When I try to view the contents of Templates it says "1: 0 2:"
Does this mean null?
<Condition Message="[TEMPLATES]">TEMPLATES</Condition>

Directories are not properties. If you want to set a directory to the value of a property you should use SetDirectory
<SetDirectory Action="SetTemplateDir" Id="TEMPLATES" Value="[TEMPLATES]">TEMPLATES</SetDirectory>
If this doesn't work you might need to look at the msi logs for more information on what is happening during the directory searches and trying to set the directory. Just run your msi from the cmd line with "msiexec /i installer.msi /l*v msilog.txt"

Related

Change the installation path

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..

How can I log a the value of a property in Wix?

I want to know if in the same directory of my setup (CURRENTDIR) there is a file named "pippo.txt". So I made the following property.
<Property Id="TROVAPIPPO">
<DirectorySearch Id="trovadir" Depth="0" Path="CURRENTDIR">
<FileSearch Id="trovafile" Name="pippo.txt" />
</DirectorySearch>
</Property>
Now I want to display the value of this property in the log file (in temp folder). But I don't know how.
Run your installer from the command line with msiexec /i yourInstaller.msi /L*v yourLogFile.txt
Changes to MSI properties will be logged. The log files are pretty big, but it'll be in there somewhere.

Using WiX to target specific folder

I'm using Wix to create an installer that will search for a directory on the user's PC and install a related application to that directory. For example, I need to install to the folder ProductA\Utilities, the location of which is outside of my control.
To accomplish this, I have tried the following:
<Property Id="UTILITIES_DIR">
<DirectorySearch Id="FindUtilsDir" Path="ProductA\Utilities"/>
</Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<!-- WiX requires me to use a special folder at some point -->
<Directory Id="ProgramFilesFolder" Name="ProgramFiles">
<Directory Id="UTILITIES_DIR">
<Directory Id="INSTALLFOLDER" Name="MyUtility"/>
</Directory>
</Directory>
</Directory>
This all works well when I'm running the installer by double clicking, however, when I run the installer through msiexec.exe, the UTILITIES_DIR is found, but overwritten immediately after:
From log file:
MSI (c) (C0:0C) [16:49:34:064]:
PROPERTY CHANGE: Adding TARGETDIR property. Its value is 'F:\'.
MSI (c) (C0:0C) [16:49:34:064]:
PROPERTY CHANGE: Modifying ProgramFilesFolder property.
Its current value is 'C:\Program Files (x86)\'. Its new value: 'F:\ProgramFiles\'.
MSI (c) (C0:0C) [16:49:34:064]:
PROPERTY CHANGE: Modifying UTILITIES_DIR property.
Its current value is 'C:\ProductA\Utilities'. Its new value: 'F:\ProgramFiles\'.
It's worth noting that F:\ on my machine is a network share to parts of C:\ and it reports the exact same free space as C:\, so it seems that I'm getting lucky when running the .msi directly and TARGETDIR is set to C:\, but when running from msiexec, TARGETDIR is getting set to F:.
Is there a way to accomplish finding a specific directory that may be in any root?
You can set the SourceDir to WindowsVolume. So it will not change anymore.
<SetDirectory Id="SourceDir " Value="[WindowsVolume]" />

Register add-ins, project templates and item templates for Visual Studio 11

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... :-/

Changing installation location based on condition

I am making installer for a utility that can be installed as part of a main program or independently. The location of the main program in present in a registry key. If the main program is installed, the utility should be installed in a "Utilities" sub-directory. e.g. D:\Program Files(x86)\MainProgram\Utilities. If the main program is not installed, then it should default to root drive folder e.g. C:\Program Files(x86)\MainProgram\Utilities.
Installation should get the registry key (e.g. HKLM\Software\MainProgram\ Key:"Install_location"). This will give a path till d:\Program File(x86)\MainProgram. The utility should be installed in its sub-directly. If the key is not present, it should default to the standard location.
Read the registry value from custom action using C# or some other language and check if key exists or else you can use WIX to find if registry key exists.
RegistryKey regKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(#"Software\MainProgram\Key");
if ((string)Registry.GetValue(regKey, "Install_location", "0") != "0")
{
session["Somevariable"] = (string)Registry.GetValue(regKey, "Install_location")
}
using WIX
<Property Id="INSTALLLOCATION">
<RegistrySearch Id="INSTALLLOCATION"
Name="Install_location"
Root="HKLM"
Key="Software\MainProgram\Key"
Type="raw" />
</Property>
On the basis of the value of WIX session variable you can decide the install location and install the utility at the desired path.
Read the MainProgram location into a property:
<Property Id="MainProgramDir">
<RegistrySearch Id="FindMainProgramDir"
Root="HKLM"
Key="Software\MainProgram"
Name="Install_location"
Type="directory" />
</Property>
And set up your directory structure for the default behavior:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MainProgramDir" Name="MainProgram">
<Directory Id="INSTALLDIR" Name="Utilities"/>
</Directory>
</Directory>
</Directory>
Directory elements are like properties, and will be overridden if there is a property with the same Id. If the property is not set (because the RegistrySearch fails) then it will be as it was defined in the directory structure you set up.