I've seen many answers to variants of this question but couldn't find a working solution plus I fail to understand some related stuff, so:
I need to abort the installation (which I'm currently creating) if our old app is already installed.
The new MSI is user-scoped and the old one is machine-scoped, so I can use this for my advantage, plus an old version number can also indicate an old MSI.
I figured out (not so much to figure out actually) the conditional install.
Regarding the indication that the old MSI is installed - At first I searched for examples how to use ProductSearch, but then I've seen a SO comment stating it only works for bundles.
So I started searching how to registry search - but although I know most of the path where the old MSI is registring in (Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall), I don't know the next subdir since it's the product code which according to this should be autogenerated for every version etc. It's also marked as * in our old wsx.
So how should I approach this? How should I search for the old MSI in the registry?
I can't scan the filesystem as the user may change the installation dir.
I prefer not to add another custom action though I will if I'll have no choice
Thanks!
Just write a Upgrade search using the UpgradeCode and ProductVersion range of the old product with the OnlyDetect attribute set to yes. This will cause the property to have a value if the old product is detected. You can then use this property in a Condition element (LaunchCondition).
Related
In my wix project the product version number is generated by a tool and we strictly want the 3rd component of the number to appear as it was generated.
Let's say the version number to use is 2.17.0043, then after the product is installed I can see it omits the leading 0s from the third component of the version showing it as 2.17.43. Even if I open the bootstrapper's outcome setup executable file Properties and switch to the Details tab page then the File or Product version are 2.17.43.
How can I preserve the 3rd part of the version to keep it's original textual look 2.17.0043?
Burn always normalizes versions as #####.#####.#####.#####. Arbitrary text like padding isn't supported.
This can serve as an answer, however, someone experienced can explain what are the differences and why does this approach work.
When I set my version in bundle.wxs then 2.17.0043 ends up to appear as 2.17.43 in Add/Remove Programs after installation. However, if I use binder variable to set the Bundle version Version="!(bind.packageVersion.MSIPackageId)", where the MSIPackageId is the Id attribute value of my Chain/MsiPackage element, then that way it preserves the 3rd version part as it was set internally in my MSI package (2.17.0043).
Stein Åsmul asked/commented to my question description above, whether I was dealing with WiX Bundle; perhaps that's the difference, that could be the trick.
In my case this is a perfect solution since I have only one MSI package under the Bundle/Chain, however, I guess if you have multiple MSI packages and the bootstrapper's generated setup exe should not inherit version number of any of the MSI packages, then this won't work, or maybe there is another way to achieve it that I'm not aware of.
We changed the UpgradeCode component to a different GUID. Is there a way to change an installed product's UpgradeCode without redoing the install?
Live?: Is the product live yet? If not, just uninstall all instances and revert to the original upgrade code? (Especially the case if you are in a corporate environment with proper control of deployment via a distribution system - then there are no constructs needed to add to the package itself for eternity).
Hotfix: Some would suggest hotfixing the cached installation database. I wouldn't even try. I find it very hacky, even when using the MSI API (Win32 functions / COM API to manipulate MSI files).
Upgrade Table: I haven't done so in ages, but you should be able to author the erronous upgrade code into your MSI file's Upgrade Table in addition to your main one. In other words, you can detect multiple related products (or even unrelated products), each with different upgrade codes by authoring the Upgrade Table. You would generally need to leave that legacy entry in there for the foreseeable future though, to ensure smooth upgrades for as long as that particular product line is relevant. You could keep using the new upgrade code, or revert to the old one (but you need both entries in there for as long as this product line updates - if you are live with all versions).
Sample: I am doing something along the lines of what is described above here: Adding entries to MSI UpgradeTable to remove related products
I'd like to know what exactly happens to installed files / components during the uninstall procedure.
For the install and upgrade procedure, reliable documentation exists at MSDN (see File Versioning Rules and Default File Versioning, for example).
Anyways, I couldn't find a documentation of the uninstall remove logic at MSDN or at WiX´s documentation.
So, my question is simple: I would like to know when exactly a file is removed from the system (which isn't always the case - for example if a SharedDLLRefCount exists/remains for that file).
The closest I found was the following MSDN link, which gives some advice, but basically says: "Test it yourself".
This isn't satisfying for me, because I would like to know if I can rely on a - maybe current - behaviour of MSI before I ship any installers using this behaviour to customers.
I'm searching for reliable answers to the following questions:
Under which circumstances - aside from an explicit "permanent" definition or using SharedDllRefCount - will a file/component survive an uninstall Action?
If a DLL has now a higher Version than at the time it was installed (because of hot patching or so) will it safely be removed? Note: I tested this and the current answer is yes, but I need to know if this is expected behaviour and if I can rely on it.
Component referencing for MSI files is done on a Windows Installer component basis - and not based on the old SharedDLL ref count found in the registry here: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs.
SharedDLL: Strangely this SharedDLL ref-counter is sometimes also used with MSI, but this is only to provide compatibility with legacy installer and deployment technologies - I will clarify later. Legacy technologies used this SharedDLL counter as the sole way to determine if a file could be uninstalled. As soon as ref-count dropped to 0, the file could be removed.
The actual reference counting for Windows Installer is done based on Windows installer components and not shared dll ref-counters. These components are "atomic installation bundles" of files and registry settings. It is always installed or uninstalled as a whole unit. A component can basically contain "anything", but there are rules with regards to best practice when decomposing the files and registry settings you want deployed into a collection of components. Personally I always use one file per component since this avoids all kinds of problems during Windows Installer upgrades.
Key Path: Essentially each component has a "key-path" - a single file or registry key / value which is used to determine if the component is installed or not. The overall concept of MSI is that there is a 1-to-1 mapping between this absolute component key path and a unique component GUID. The GUID essentially reference counts that absolute path. I explained this in an answer several years ago, and it seems to be a comprehensible explanation for people, perhaps give it a quick read to understand this component referencing in more detail: Change my component GUID in wix?
Merge Modules: This component GUID - for that particular absolute disk or registry location - should be used by all setups that seek to deploy the file or component in question. Window Installer's mechanism to allow this is referred to as a "merge module". This is a partial MSI database that can be merged into several MSI files at build time - allowing the same components to be shared between MSI files with the correct component GUID used in all of them so that reference counting is possible. This allows these shared components to increment the ref-count each time they are installed by different products, and then the component will remain on the system until the ref-count is reduced to 0 as the products that use it are uninstalled in sequence. It should be noted that if the legacy ref-counter at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs is not 0 at the same time, then the component will not be uninstalled. Nor will it be uninstalled if the component is set permanent or if it was installed with a blank component GUID (a special feature to "install and forget" a component - it is never dealt with again).
GUIDs: So to repeat yet again, one GUID for one absolute path (one GUID to rule them all) - one GUID has an associated ref-counter which counts the number of products that have registered the component, with its associated absolute key-path, for its use. So, as an example three products might register use of a certain component GUID, making its reference count 3, and hence making its associated key-path file or registry value stick around until all 3 products are uninstalled.
SharedDLL Enabled?: Note that the legacy SharedDLL ref-counter is not necessarily enabled for your MSI components. Some tools, such as Installshield, enable a flag to increment the legacy, shared DLL ref-counter for all files installed and you actually have to turn it off for each component to get rid of this behavior. This is in contrast to other tools, such as WiX, which does not default the shared dll ref-counter to be on for all files (I am not sure for what files they do enable it - if any). Advanced Installer also does not enable the SharedDLL ref-count flag for all components (thanks to Bogdan Mitrache for verifying this - see his comment below).
Messed up legacy reference counters - which can happen during development and test installation - may cause a Windows Installer
component that should be uninstalled to be left on disk unexpectedly.
If you see this, check on a clean system to determine if messed up
legacy ref-counters is the problem on your main machine. You then need
to manually tweak the registry to fix the ref-count for your
development machine. That will involve all applicable items under this
key: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs.
Not a fun job - I had it happen when using Installshield Developer 7
way back in the day.
Failing to keep a consistent component GUID for each absolute key path will cause mysterious and unpredictable problems such as an MSI
uninstall removing files that are still shared with other products,
but the reference counting has been messed up. The MSI files
mistakenly believe they "own" the shared component and happily deletes
them. A case of mistaken identity (the same absolute path has multiple
component GUIDs pointing to it - each one reference counted to 1).
This is one of the key problems people face with Windows Installer -
hence the advice to stick with one file per component.
Update: Let's be concrete about your specific questions.
You have already pretty much answered the question. The file will remain on disk if the component's ref-count (for the component GUID) is higher than 0 after your MSI file has decremented its "registration" of it on uninstall. It will also remain if its MSI component is set to be permanent, or if it had a blank component GUID, or if the legacy SharedDLL ref-count was enabled for the component (it may not be) and the ref-count here is higher than 0: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs. Those are all the conditions I know about. I suppose there are other aspects such as advertised products, but I am honestly not sure how they will affect uninstall. Advertised products are not really installed, but "installable" by the user on demand. Reading Phil's answer I also recall that transitive components can also be uninstalled in the fashion he describes in his answer - by having the associated condition evaluate to false during reinstall.
Yes, as long as the component GUID has remained stable throught the lifetime of a specific absolute path (the full installation path for a file), then that file can have gone through any number of updates, and the reference count is only incremented if another MSI with another product code also installs it. In other words: if you have delivered 4 updates to your original MSI, and you have maintained a consistent component GUID for a specific file and updated it each time with a new version, then the component ref-count for this file is still 1 - as long as no other MSI has also installed the component - in which case it will be 2 or more, and an uninstall of your product will not uninstall it, but reduce the ref-count by 1.
Please do try to read this answer since it seems to have clarified things for other people: Change my component GUID in wix? (same as recommended above).
Finally I should note that shared components can also be installed via WiX include files - a new concept entirely introduced with WiX. These are like regular include files in C++, you simply define them once and they can be included in several WiX source files at compile time. I have honestly never made use of this, but conceptually it is similar to merge modules - the built-in Windows Installer concept to deal with shared components. There is one important difference though: merge modules are versioned as a whole, whereas WiX include files include files dynamically from your source folder. I find this better, but this is certainly a large discussion and a matter of preference. I will not elaborate this here.
If you are using WiX I would recommend you try to use WiX include files to manage your shared components. They seem - to me - to be a more flexible implementation of merge modules. On a subjective note I have never been a huge fan of merge modules, though they are essential to use if you have lots of shared files to install with different products. Why do I not like merge modules? They seem like an extra complication and a binary blob that needs extra maintenance. In effect they amount to a weird form of static linking - with all the problems we know from regular static linking. This may be getting too subjective, so I will end on that note, but for shared files and components use either merge modules or WiX include files or whatever other construct exist to achieve the same that I am not aware of.
There really are only a few rules that apply, but the difficulty is that they apply in a number of sometimes complicated scenarios.
A resource (a file) is removed if its component id ref count goes to zero and:
a) there is no remaining SharedDllRefcount for it.
b) the component has never been marked permanent in the installing MSI (because that makes it stick and can't be turned off).
c) the component was set to Transitive and an install/maintenance operation takes place that sets the associated property value to "false". Again, this is sticky to the system, not a project setting.
d) it has not been marked as msidbComponentAttributesShared by an install.
Permanent, transitive, component shared, and shared Dll can be set on a component.
Versioned shared files do not revert to the previous binary if product A installs version 1 and product B installs version 2 and then product B is uninstalled. By definition (it not always in practice) shared files need to support older clients.
During a major upgrade with RemoveExistingProducts (REP) at the "end", the upgrade applies file versioning rules for files, and increases the ref counts of components that are already installed (or installs the component if it's new with a ref count of 1). In this kind of upgrade the components are effectively shared with the same component ids that are already installed by the older product. When REP uninstalls the older product the ref counts are decremented.
So in the simplest case of an upgrade containing all identical component ids, no files are removed: if component ids A, B, C and D are in the older installed product and component ids A, B, C, and D are in the new upgrade then file versioning rules were applied and decrementing ref count leaves the files there, perhaps with higher version, when REP removes the older product. This why component rules must be followed with this kind of upgrade, or patch, or upgrade by reinstalling with REINSTALLMODE=vomus REINSTALL=ALL.
If component ids A, B, C and D are in the older installed product and component ids A, B, C, and E are in the new upgrade then the same happens except D will be removed because its ref count is zero now, assuming there are no other clients and the rules above do not apply.
Major upgrades with REP "early" are simple in the best case because it's an uninstall of the old product followed by an install of the new, so older versions of files could be installed, and again files are removed or not according to the above rules. None of the component ids need to be the same in the simplest case that there are no shared files used by other products.
Common issues involve setting components to permanent or Shared Dll (which is required ONLY if the file is shared with a non-MSI install). There seems to be the idea that these can be turned off by doing another install that changes them, but these are system settings, not project settings.
I've googled a lot, but there's little information about my question.
The question for short is "Suppose you have the target image(.msi), the list of changed binaries, but you don't have the upgrade image. How to make a patch based on those inputs?".
The detailed description is:
Currently, We use TFS as the source control. And each time when making a new MSI, we will increment the AssemblyFileVersion of all projects whether the project is really changed or not firstly. This is fine when there's no requirement to make a patch.But, actually, we DO have the requirement to make a patch now. I have tried to create a patch using Purely WiX or Patch Creation Properties, but almost all projects will be considered as changed when we use these MSIs directly.So if I have three inputs:
Target Image(.msi)
A list of really changed binaries
Upgrade Image(all binaries' file version is incremented) <--- this input may be useless
How Can I make use of above inputs to create a patch?
Thanks in advance.
Alternative to Phils answer, you could add an ignore switch for the only incremented files in your Patch Creative Properties File.
<UpgradeFile File="YourFileID" Ignore="yes" />
see
http://wixtoolset.org/documentation/manual/v3/xsd/wix/upgradefile.html
Depending on how many files there are to ignore might make Phils method easier. Although if you get the file table id list (export the table in orca and edit in excel, copy A3 down) and remove all the ids from you're really changed list, then add the xml around each id..it shouldn't take long.
You can still use the upgraded MSI build when you make a patch. I don't know all the WiX things you may need to do, but I've done exactly what you want to do by setting IgnoreMissingSrcFiles in the TargetImages table:
http://msdn.microsoft.com/en-us/library/aa372066(v=vs.85).aspx
and just delete all the files you don't want to be patched. You use admin images anyway to create the patch, so all you'll have are two admin images wiyth MSI files and only the files you want to patch.
I am in the process of creating an MSI for our product. I would like the product to be able to install side-by-side. So that I can install 1.0.0 first and later can add 1.0.1 so that the two versions are both installed.
I am using WiX to create the msi and would like to know how this can and should be done in Wix? For example
Do I need to create new Guids for all components?
How would i add the version info to wix or should i rename my product completely?
How can I create the projects so that releasing a new version requires minimal changes in the wix project?
Greetings,
Martijn
You should be able to get away with just changing the top-level productcode and UpgradeCode GUIDs to make your two products completely unrelated, and use the Productversion to identify the version. You can share component guids between products (that's how merge modules work) so that the guts of your installer (component definitions) needn't be tweaked and can still be shared.
You major challenge will be ensuring that the two decoupled products don't interfere with one another, for example by having the same default installation folder, start menu entries and the same Add/Remove programs entry. You might achieve this by including the product version number in the ProductName Property, which can look a bit techy in your install UI, but it isn't unheard of.
Regarding your first question: No, you don't need to.
But why?
I had difficulties to understand the windows installer rules in my side-by-side scenario.
You really need to understand the concepts of component rules (including when you need to brake them) and key paths. WiX doesn't abstract these aspects away.
This answer does already highlight possible interferences.
Let's consider a few examples.
The GUID of the component with the application executable does not need to be changed. This breaks the component rules, but it works, as both versions of the product define the same component in a non-interfering way.
A resource shared by both versions is not directly supported. A prominent example is the use of file extensions using ProgIDs, as shown here.
If you change the GUID (also happening when using the "*" GUID), the extension will be removed when uninstalling either version.
If you don't change the GUID, the extension will be retained, but point to the version which was installed most recently. You may go with this option as the lesser of two devils, supporting at least a scenario where users uninstall the versions in the same order in which they installed them.
There is a pitfall here: The extension needs to be the key path of the component. This makes the usage of the ProgID element problematic in a side-by-side scenario as you'll get the ICE69 warning in case you don't put the ProgID element in the same component as the referenced file. Further more, it's an implementation detail of WiX which registry entry it generates will be the key path.