Should the App.Config be a companion file to the application or go in its own component? - wix

When I create a Windows Installer package (say using WiX) and I install the application App.exe as well as the App.exe.config should the config file have its own component or should it be a companion file to the application executable?
<Component Id="C.App.exe">
<File Source="App.exe"/>
</Component>
<Component Id="C.App.exe.config">
<File Source="App.exe.config"/>
</Component>
versus
<Component Id="C.App.exe" Guid="PUT-GUID-HERE">
<File Id="F.App.exe" Source="App.exe"/>
<File Source="App.exe.config" CompanionFile="F.App.exe"/>
</Component>
If I install different App.exe.config files depending on some external property (say run-time environment like test or release) does that affect what choice I should make?

The answer is it depends. Rob's article mentioned by Yan is a good read, here is another:
Defining Installer Components
http://msdn.microsoft.com/en-us/library/aa368269(VS.85).aspx
The trick is to understand how costing and repairs are based on keyfiles, how the default versioning rules work, how you plan on servicing your application in the future and making your decision based on that.

It is recommended to put a single resource (file, registry key, etc.) into a single component. In this case this resource is a KeyPath of the component. Windows Installer watches the key path of each component to decide if it worth installing, repairing, upgrading, etc.
This article of Rob Mensching explains the things in detail.

Related

Make Wix to not uninstall common dll

I have Wix project in which I need a common used dll library to be installed if it's absent.
If this dll exists I should not overwrite it.
So, when I set DefaultVersion="0.0.0.0" this dll is not overwritten if it exists, its ok. But when I delete app, the dll is beeing removed. How do I prevent removing dll in the case when it existed before installation?
I don't want to make it permanent because it should be removed if it didn't exist before installation.
<Component Id="myLib.dll" Permanent="no" Directory="Shared_Dir">
<File Name="myLib.dll" KeyPath="yes"
Source="mySource\myLib.dll"
DefaultVersion="0.0.0.0"
/>
Add reference to WixUtilExtension and xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" attribute to Wix element in your code.
Define <Property Id="Dll_Installed" Value="false"/> in Product element.
Add child <Condition>NOT Dll_Installed</Condition> to component myLib.dll.
Add that somewhere in your code:
<Fragment>
<util:FileSearch
Id="Dll_Installed"
Variable="Dll_Installed"
Path="[Shared_Dir]myLib.dll"
Result="exists"/>
</Fragment>
DefaultVersion attribute is not necessary.
The feature you are describing is reference counting. The Windows Installer reference counts with Components. Components are identified by their GUID.
So the normal way to address this requirement is to put the File in a Component and make sure the GUID of the Component is stable. The WiX Toolset should do exactly that automatically if if you do not specify the Component/#Guid attribute.
So the default behavior should just work for you.
The only other piece of the puzzle is the Windows Installer will install the latest version of a file. If the file version is the same or less the file will not be installed but will be reference counted.
Based on the details in the question it seems like you should be just fine with:
<Component Directory="Shared_Dir">
<File Source="mySource\myLib.dll" />
</Component>
One might ask why the Windows Installer use Components to reference count files. We'll, it allows you to group other resources, like registry keys, together and control their install as a unit. Much more important if you are installing COM servers than plain old files.

Wix component GUID "*" is not valid for this component

I'm trying to solve my issue with autogerating GUID for multiple components in same folder installed under AppData (per-user installation).
Before edit I had one component with 3 files. Then I've decided to use auto GUID for this component, so I have divided it into 3 component (each with one file). I thought that now I can use Component GUID with * and registry value with KeyPath=yes but it's not working. Any advice is very appreciated.
Here is code snippet:
<Directory Id='INSTALLDIR' Name='$(var.myInstallDir)'>
<Component Id='MainExecutable' Guid='I_WOULD_LIKE_ASTERISK_HERE_ALSO_BUT_HAVE_HARD_CODED_GUID' >
<RemoveFolder Id='RemoveINSTALLDIR' Directory='INSTALLDIR' On='uninstall' />
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Name='Path' Value='[INSTALLDIR]' KeyPath='yes'/>
<File Id='ffile1' Name='file1' DiskId='1' Source='file1'> </File>
<Shortcut Id="startmenujfile" Directory="ProgramMenuDir" Name='$(var.myAppName)'
Target="[SystemFolder]cmd.exe" Arguments=" /c START javaw.exe -jar [INSTALLDIR]file1.jar ."
WorkingDirectory="INSTALLDIR"
Icon="apsoiconmultiico" IconIndex="0" />
<Shortcut Id="desktopjfile" Directory="DesktopFolder" Name='$(var.myAppName)'
Target="[INSTALLDIR]file1.jar" Arguments=" ."
WorkingDirectory="INSTALLDIR"
Icon="iconmultiico" IconIndex="0" />
</Component>
<Component Id='MainExecutable2' >
<File Id='ffile2' Name='file2' DiskId='1' Source='file2' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes'/>
</Component>
<Component Id='MainExecutable3' >
<File Id='ffile3' Name='file3' DiskId='1' Source='file3' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes'/>
</Component>
</Directory>
And error for components:
error CNDL0230 : The Component/#Guid attribute's value '*' is not valid for this component because it does not meet the criteria for having an automatically generated guid. Components with registry keypaths and files cannot use an automatically generated guid. Create multiple components, each with one file and/or one registry value keypath, to use automatically generated guids.
Thank you
EDIT:
Thanks to #Stein Åsmul answer. I need to ask one more time..
I'm trying to solve this because we are moving from Java Web Start (jnlp) to very simple .msi file which installs only elementary files and shortcuts. Then the app itself has automatical update system which downloads all other files.
Our app can have "mupliple sets of versions" installed on same machine (like set A: "app 1 demo, app 2 test" and set B: "app 2 demo, app 2 test"). Every set and every version in the set can have different files (this is a job for update system itself).
Now the question. I'm a newbie in .msi installation so I'm not sure about many steps. I know productId, upgradecode.. but what about component GUID (in my case Component Id='MainExecutable') in enviroment with multiple sets of app installed on same machine (per-user but different directory - AppData/local/setA and AppData/local/setB) with registry KeyPath=yes? Can this component has fixed GUID for all our installations if productId is different (so hardcoded in .wxs for all installations)? Thank you for explanation.
Short Answer: You cannot use auto-guids for components that have the same / non-unique key path - which is the case for per-user registry key paths. Simpler approach: Install files to a per-machine location and copy them into each user-profile on application launch instead of
installing them per-user via an MSI. This de-couples all user-profile files
from common deployment problems (overwriting / resetting, upgrade problems, uninstall problems, etc...). Auto-Guids are possible for per-machine key paths - they are unique per component.
Per-User Key Path: HKCU\Software\Company\Product\MyKeyPath
Repeats for every user! => No auto-guid possible. It is not unique.
User 1: C:\Profiles\User1\Product\File.exe, Key path: HKCU\Software\Product\MyKeyPath
User 2: C:\Profiles\User2\Product\File.exe, Key path: HKCU\Software\Product\MyKeyPath
For the record, here is what would happen if you set a userprofile disk-based key-path (as opposed to a registry key path which you are supposed to use): Color illustration.
Per-Machine Key Path: C:\Program Files\Company\Product\Main.exe
Only one installation instance! Unique key path allows auto-guid.
Read-Only Templates: A general issue first: it is recommended that you don't install files directly into the user profile folders. Rather you should install them to your main installation folder under Program Files and then copy them in place during application launch for every user who uses the application. The files can then be copied to every user-profile on demand and on launch of the application (upgrades are possible too, if you implement it well).
Technically: You cannot use an auto-guid for components that has the same / non-unique key path. The technical reasons can perhaps be best understood by reading this old answer: Change my component GUID in wix? Essentially the key path must be unique in order to be able to create an automatic GUID, and this is not the case with per-user registry keys. The path is the same for all users - to the same registry key (even if the content is different for each user). A limitation of the MSI technology.
Note that if you install to a per-machine path you will be able to use auto-GUIDs since you can have a unique file key path for the component. This should work fine. Just move the files to a per-machine path and set an auto-guid. Upgraded files will overwrite older files and you can copy newer files over the ones in the user profile on launch - if desirable. A risky operation most of the time.
Cloud: I am fond of cloud-based approaches to download files into the user profile on-demand directly from the Internet or Intranet as an alternative to deployment via MSI. It all depends what you have access to.
More Details: There are too many pre-existing answers that revolve around the same points for there to be any value in rewriting it. Please check the below links for more details on the deployment of per-user files with MSI:
Create folder and file on Current user profile, from Admin Profile
Wix deferred custom action access denied
How to create nested folder in AppData
Create a .config folder in the user folder
Make WIX installer place files in AppData

Merge module files into different locations

I'd like to parse merge module files into two different locations. Is it possible?
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="MergeRedirectFolder">
<Component Id="LoggerClient" Guid="*">
<File Id="log4net" Name="log4net.dll" Source="..\..\_Release\log4net.dll" KeyPath='yes' />
<File Id="LoggerLibrary" Name="LoggerLibrary.dll" Source="..\..\_$(var.Configuration)\LoggerLibrary.dll" />
<File Id="app.config" Name="app.config.xml" Source="..\..\_Release\app.config.xml" />
<File Id="msvcr110.dll" Name="msvcr110.dll" Source="c:\windows\sysWoW64\msvcr110.dll" />
</Component>
</Directory>
</Directory>
</Module>
<Merge Id ="MergeModule.msm" Language ="!(loc.Lang)" SourceFile ="_$(var.Configuration)\MergeModule.msm" DiskId ="1" />
I want the second file to copy to a different folder than the other files.
There is a concept for that, it is called a retargetable merge module. I have avoided used it - the concept doesn't seem right to me. I have not tried to make one with Wix.
I think you could combine a Wix include file (simple sample) with the new auto-generated component guids to deploy such duplicated files reliably by adding an Include statement where appropriate. You must not hard code the guids in this case, but let them be auto generated by the Wix compiler and linker.
Also have a read of WixLibs (Wix library files): http://robmensching.com/blog/posts/2008/10/10/what-are-.wixlibs-and-why-would-you-use-them/
Wix documentation; http://wixtoolset.org/documentation/manual/v3/overview/files.html
Merge modules are for installing common runtimes and genuinly shared files. Typically C and C++ runtimes and other, similar libraries that should be available in the latest version for all applications.
Your files look like they are part of your application folder, with the exception of msvcr110.dll which you should remove and allow to be loaded from the system folder.
If the remaining files have no per-machine registration (COM for example or COM Interop), you can duplicate them in several folders without interference, yes, but why not load them from a shared location inside your own application folder structure?
%ProgramFiles%\My Company\My Shared Runtimes
%ProgramFiles%\My Company\My Apps\My App 1\
%ProgramFiles%\My Company\My Apps\My App 2\
These sample folders you "own" and you can deploy things here however you like. Not so for shared, system folders. You could make your own merge module for shared components between your applications into "My Shared Runtimes" and make your applications aware of the shared location "....\MySharedRuntimes\"
It depends on what you mean by different locations. You can build a merge module with 4 files, each in their own component and directory. One could go to the CommonFilesFolder; another to the SystemFolder; another to...you get the idea. So it's potentially easy if you make each file its own component in its own directory. However you've got them all under TARGETDIR, so you're going the wrong direction. You just define the other directory and that other component and file and you might be done, unless there's more to the question than meets the eye.
I would suggest contacting me privately for a few 30-60 minute conversation on MSI, component rules, Merge Modules and file set theory. It's too much to write. In a nutshell I would advise more merge modules.

What elements does Wix use to auto generate a ComponentId guid when the keypath is a RegistryKey/Value

I have a Wix (3.8) project that is relatively generic in that we are attempting to produce multiple Demo installers using a variety of tools such as the preprocessor to change the name, include different files and options. I also modify the ProductId/ProductCode/UpgradeCode for each so that they appear as 2 different products and install side by side. Installing and uninstalling one alone works fine. When I install 2 side-by-side and uninstall one there are several abandoned resources one of which is the shortcuts.
Here is the code I am using for the shortcuts:
<DirectoryRef Id="DesktopFolder">
<Component Id="DesktopShortcuts"
Guid="*">
<Shortcut Id="ApplicationDesktopShortcut"
Name="!(bind.property.ProductName)"
Description="Demo Application"
Target="[INSTALLDIR]Demo.exe"
WorkingDirectory="INSTALLDIR"
Advertise="no"/>
<RegistryKey Root="HKMU"
Key="SOFTWARE\$(var.Manufacturer)\!(bind.property.ProductCode)\DesktopShortcuts">
<RegistryValue Name="Installed"
Type="integer"
Value="1"
KeyPath="yes" />
</RegistryKey>
</Component>
</DirectoryRef>
After reviewing the installer logs I note that the ComponentId for the shortcuts is always the same which explains the abandoned resources (shortcuts).
I was under the impression that because the Path to my registry value was different for each installer (note that I bind the product code into the key) I would get a different Guid for each installer as a result of the Guid="*" attribute. However, the wix documenation is unclear WRT Registry keys as are other discussions I located. Apparently this isn't an issue with files that are in separate directories.
Such as this and the Wix docs.
So I figured out what is going on. It's all got to do with some subtle issues on this line:
Key="SOFTWARE\$(var.Manufacturer)\!(bind.property.ProductCode)\DesktopShortcuts">
As noted in the question the documentation and references suggest that the Path for files and registry entries are used to dynamically generate the Guid. Note the path includes the file/Value Name. This is in fact happening but how was I getting the same Guid for the ComponentId for 2 different installers using 2 different ProductCodes? You would think that the inclusion of the ProductCode into the path would make each unique. Well, turns out it's because I was using !(bind.property.ProductCode) in the path. Binder variables don't get substituted until the Linking phase with light. The Guid="*" element is generated in the Compiling phase with Candle which is obviously before the linker. So while the substitution was occurring and the proper keys were being generated in the registry, the Guid was being generated from a non unique path:
SOFTWARE\MyCompany, Inc\!(bind.property.ProductCode)\DesktopShortcuts\Installed
So don't use binder variables in any KeyPath element when using the auto generated Guid functionality.

WiX: Component rules for installing an application with an application manifest

I'm writing an installer using WiX 3.7. The installer will install an old VB6 program (it's a vendor-proprietary program for which I do not have the source code). As such, this program makes use of some old COM libraries that are not installed with the most recent versions of Windows (e.g. Windows 7 and beyond—not sure about Vista or XP).
Since I recently learned that COM libraries can now be installed privately without global system registration using registry-free COM registration, this is precisely what I intend to do for those COM libraries that are no longer distributed with the Windows OS.
To that end, I've created the required manifest files that will be used to lookup all the COM registration information when the library is loaded and used by the application. I've created MSI components for these libraries. Here's the relevant WiX markup for these two libraries (I've removed my GUIDs for the components so no one copies them for their own installer):
<Component Id="C__MsComm32.ocx" Guid="PUT-YOUR-GUID-HERE" DiskId="1">
<File Id="F__MsComm32.ocx" Vital="yes" KeyPath="yes"
Assembly="win32"
AssemblyApplication="F__MyApp.exe"
AssemblyManifest="F__MsComm32.sxs.manifest"
Name="mscomm32.ocx" Source="[to be filled in]" />
<File Id="F__MsComm32.sxs.manifest" Vital="yes" KeyPath="no"
Name="mscomm32.sxs.manifest" Source="[to be filled in]" />
</Component>
<Component Id="C__threed32.ocx" Guid="PUT-YOUR-GUID-HERE" DiskId="1">
<File Id="F__threed32.ocx" Vital="yes" KeyPath="yes"
Assembly="win32"
AssemblyApplication="F__MyApp.exe"
AssemblyManifest="F__threed32.sxs.manifest"
Name="threed32.ocx" Source="[to be filled in]" />
<File Id="F__threed32.sxs.manifest" Vital="yes" KeyPath="no"
Name="threed32.sxs.manifest" Source="[to be filled in]" />
</Component>
In order for all of this to work, I also need to provide a manifest file for the application exectuable, called MyApp.exe.manifest that tells the OS which assemblies this application depends on. So I also created the requisite manifest file. Now I need to create the component (or components) for deploying the application and its manifest.
According to the VS intellisense for File/#Assembly:
Specifies if this File is a Win32 Assembly or .NET Assembly that needs to be installed into the Global Assembly Cache (GAC). If the value is '.net' or 'win32', this file must also be the key path of the Component.
And then, for File/#AssemblyManifest:
Specifies the File identifier of the manifest file that describes the assembly. The manifest should be in the same Component as the assembly it describes. This attribute may only be specified if the Assembly attribute is set to '.net' or 'win32'.
That's all well and good, and I understand all of that completely. So for my application's File element in WiX, I have this so far:
<File Id="F__MyApp.exe" Vital="yes" KeyPath="yes"
Assembly="win32"
AssemblyManifest="F__MyApp.exe.manifest" />
Now, what I don't understand is the intellisense for the File/#AssemblyApplication attribute:
Specifies the identifier for the application file. This assembly will be isolated to the same directory as the application file. If this attribute is absent, the assembly will be installed to the Global Assembly Cache (GAC).
Obviously, I don't want my application installed into the GAC (and, I think it shouldn't be since I set File/#Assembly to win32). The question is, can the File/#AssemblyApplication attribute value point to its parent element's #Id attribute? For example:
<Component Id="C__MyApp.exe" Guid="PUT-YOUR-GUID-HERE" DiskId="1">
<File Id="F__MyApp.exe" Vital="yes" KeyPath="yes"
Assembly="win32"
AssemblyManifest="F__MyApp.exe.manifest"
AssemblyApplication="F__MyApp.exe" />
<!-- #AssemblyApplication references it's parent element's #Id attribute. -->
<File Id="F__MyApp.exe.manifest" Vital="yes" KeyPath="no"
Name="MyApp.exe.manifest" Source="[to be filled in]" />
</Component>
Is this the correct way to author the Component element for my application which contains an application manifest? Or should I forget about setting the various Assembly* attributes and create two Components, one for the application executable and another for its manifest?
Isolated COM: What you need is an isolated COM component, this is a different concept than Win32 assemblies (WinSxS) and .NET
assemblies (GAC).
Quick Advice:
My 2 Cents: Run this legacy application on a virtual machine instead! Problem solved? (problem removed maybe).
Warning: the below was written in a rush. I will check it again later.
The real expert on this (of old) is Wim Coenen - not sure he lurks this tag anymore:
Generate manifest files for registration-free COM
Side-By-Side: These two types of assembles are win32 files installed side-by-side (WinSxS) or .NET assemblies installed side-by-side (GAC) respectively. So that means old Win32 files (native code) and modern .NET assemblies (managed code - .NET runtime required). Side-by-side obviously means that different versions of the same file (referred to as assembly) can co-exist and you can load the one you require by means of a manifest.
Isolated COM: Isolated COM is something completely different. It is the installation and invocation of COM servers without any registry entanglements - all happening from within the same installation folder. I often refer to this as "registrationless COM" - an odd term perhaps.
What it means is that you can load incompatible COM server versions
from the local installation folder for whatever binary consumes them.
All you need to do is to dump the COM server and its manifest in the
local installation folder. No need for Win32 or .NET assembly
installation. See below for reality check...
This "solves" a huge problem with COM, namely the per-machine or global registration nature of COM servers. In other words there is usually only one version of the COM server installed (though it is technically possible to install different flavors of COM servers it was usually not done - a nightmare of GUIDs and IDs to change).
It also helps to isolate your application from dirty packages, installers, scripts and applications that trigger COM registration conflict in the registry. A very problematic issue ever since COM arrived.
WiX Markup: Just install the COM server and the manifest file in the same folder:
<Component>
<File Source="mscomm32.ocx" />
<File Source="mscomm32.sxs.manifest" />
</Component>
<Component>
<File Source="threed32.ocx" />
<File Source="threed32.sxs.manifest" />
</Component>
Reality Check: My experience is that it is very hard to get isolated COM to work when you don't have access to the source code in question. The reason is that COM is a binary standard / binary reuse. As I understand it you need the exact same version of the files involved for this isolated COM to work properly. All files in correct version. That is not to say that people have not succeeded using the approach, but I have generally suggested that people go virtual instead: rely on virtual machines to run these legacy applications.
I have this old answer with more context: What do I do when launching an application triggers repeating, endless Windows Installer self-repair? (see registration-less COM section).