Is Component/#Guid attribute is a MUST in case of producing MergeModule - wix

In my .wxs file for components, there are only components with single file, and this is the case for generatable GUIDs.
But it seems to me that for .msm (merge module), component's GUID should be explicitly specified. Or I'm free to use Guid="*" and that would be OK?
I tried this:<Component Guid="*">
<File Id="$(var.Logger.TargetFileName)" Source="$(var.Logger.TargetPath)" KeyPath="yes" />
</Component>
And got an error from light, that
path for key file of the component is not rooted in one of the
standard directories (like ProgramFilesFolder)
...
I'm confused, because this path is rooted in ProgramFiles:<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="ProductVendor" Name="$(var.BaseProductVendorDirectory)">
<Directory Id="BaseProductDirectory" Name="$(var.BaseProductName)">
<Directory Id="ConfiguratorDir" Name="Configurator" />
</Directory>
</Directory>
</Directory>
</Directory>

You should be able to use automatically generated GUIDs in merge modules with rooted directories. But changes introduced in WIX 3.6 probably makes this impossible until bug http://wixtoolset.org/issues/3810/ is fixed.
See also http://wixtoolset.org/issues/2353/.
And also http://sourceforge.net/p/wix/mailman/message/29956690/ (click the View entire thread link to see the full discussion).

Related

How to define installation folder from command line parameter in Wix installer

I install my application to a specific folder using the below wxs code:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="CompanyName">
<Directory Id="SUBDIR" Name="Application Launcher">
<Component Id="ApplicationFiles" Guid="*">
<File Name="app.exe" Id="AppFile1" Source="app.exe" Vital="yes" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
I want to specify the installation folder with a parameter to be given from the command line like below:
msiexec.exe /i setup.msi PATH=C:\MyCompany\Folder\ /qn
Thanks a lot.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="CompanyFolder" Name="CompanyName">
<Directory Id="INSTALLLOCATION" Name="Application Launcher">
<Component Id="ApplicationFiles" Guid="*">
<File Name="app.exe" Id="AppFile1" Source="app.exe" Vital="yes" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
For your install:
msiexec /I setup.msi INSTALLLOCATION=C:\Somewhere /qn
I am adding as an answer to get proper links. You should check out Wix's auto-generate GUID feature: WIX Autogenerate GUID *?
This feature allows you to stop generating your own GUIDs and have Wix take care of them in an "automagic" way. I haven't tested it, but anything that makes your source file cleaner, shorter, and easier to maintain is worth trying. It also makes it easier to share Wix snippets without people reusing your generated GUID.
Maybe also check out:
How To: Generate a GUID
Change my component GUID in wix?
WIX Autogenerate GUID *
Rob Mensching (Wix author) states it is safe for normal use
And one more thing with regards to properties. In general all PUBLIC properties (uppercase) can be set on the command line. If you want to use these properties in deferred mode custom actions you need to check out the concept of restricted public properties and the SecureCustomProperties property. Some Installshield info too. And a nice old Wise article.

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

Wix project references on multiple destination locations how?

I'm struggling with wix setup for one project I'm working on.
I have decided to give a wix try and it is not going well so far.
I have read probably all tutorials and searched net without success.
Here is my situation:
One setup should install in program files app folder
1.) Windows forms application
2.) Web application that is used by windows application
3.) Shared lib1 used by web and win application
4.) Shared lib2 used by web and win application
... etc
I'm using project references to collect project output with heat.
I have given each project directory id so I can later use this as reference in real install location.
It looks like I can't have same project output on more than one location
I can't have same project referenced more than once also.
How can I make installer that is using project outputs on more than one destination location.
Here is example from my product.wxs
<!-- Define Directory Structure -->
<Directory Id="TARGETDIR" Name="SourceDir">
<!-- ProgramFiles -->
<Directory Id="ProgramFilesFolder">
<Directory Id="dirManufacturer" Name="TEST_[Manufacturer]">
<Directory Id="INSTALLLOCATION" Name="TEST_[ProductName]">
<!-- Filled With Referenced project -->
<Directory Id="dirControl" Name="Control">
<Directory Id="dirControlOutput" />
<Directory Id="dirSearchAndIndexOutput" />
<Directory Id="dirControlLib" />
<Directory Id="dirControlAndWebLib" />
<Directory Id="dirLuceneAnalyzersOutput" />
</Directory>
<!-- Filled With Referenced project -->
<Directory Id="dirWeb" Name="Web">
<Directory Id="dirWebOutput" />
<Directory Id="dirWebBin" Name="bin">
<Directory Id="dirUrlRewriterOutput" />
<Directory Id="dirSearchAndIndexOutput" />
<!-- TODO: Fix This
<Directory Id="dirSearchAndIndexOutput" />
<Directory Id="dirControlAndWebLib" />
<Directory Id="dirLuceneAnalyzersOutput" />
-->
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
<!-- StartMenu -->
<Directory Id="ProgramMenuFolder">
<Directory Id="dirProgramsMenu" Name="TEST_[ProductName]">
</Directory>
</Directory>
<!-- CommonApplicationData -->
</Directory>
I'm really trying to understand how all of this works but everything I have found points out that this scenario is either impossible or requires hard manual referencing files directly.
My general idea is to have Visual Studio solution that is automatically builds setup for each source change.
Thank you for help and sudgestions!
Goran
From 3. and 4. in the description I gather you need the same file installed on different places, right?
You could do it like in the example below - same file (path\to\lib1.dll on the build machine) will be installed twice on the target machine, as App\lib1.dll and as Web\lib1.dll. You just need 2 different components that reference the same source file.
<Directory Id="AppDir" Name="App">
<Component Id='lib1_app.dll' Guid='*'>
<File Id='lib1_app' Name='lib1.dll' Source='path\to\lib1.dll' KeyPath='yes'>
</Component>
</Directory>
<Directory Id="WebDir" Name="Web">
<Component Id='lib1_web.dll' Guid='*'>
<File Id='lib1_web' Name='lib1.dll' Source='path\to\lib1.dll' KeyPath='yes'>
</Component>
</Directory>