I have created a patch (.msp) in Wix toolset and this Updating my project as I would expect.
However I am having trouble creating a second patch on top of this, and have a few questions I was hoping someone could help with.
1) When generating the transformation do I do this from the original unpatched .msi or from the .msi containing the fixes that would have been included in patch 1.
2) In my Patch.wxs - what process do I need to follow? Things I have tried including incrementing the media id, increasing the version number of the patch family? Maybe I need a whole new patch family? Do I need a new cabinet file?
3) How do I add this new patch to my bootstrapper? Simply adding another node causes multiple control panel entries.
I'm not sure what source code to provide, so if you need anymore let me know.
Patch.wxs:
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Patch AllowRemoval='no' Manufacturer='Test' DisplayName='Test' Description='Test'
Classification='Update'>
<Media Id='3' Cabinet='TestPatch.cab'>
<PatchBaseline Id='TestPatch'>
<Validate UpgradeCode='yes' ProductVersion='Update' ProductVersionOperator='LesserOrEqual' ProductId='yes' />
</PatchBaseline>
</Media>
<PatchFamilyRef Id='TestPatchFamily' />
<PatchFamily Id='TestPatchFamily' Version='2.0.0.0' Supersede='yes'>
<PropertyRef Id='ProductVersion' />
<ComponentRef Id='MainExecutable' />
</PatchFamily>
</Patch>
My Bundle.wxs in the Bootstrapper was fine, I had to add the
MinorUpdateTargetRTM="yes"
attribute to the Patch element.
Thank you to this post.
Related
I have a simple installer and I want to be able to perform upgrades and do proper uninstalls without having to manually generate a new ID each time.
This is my code (the relevant parts):
<Product Id="*" UpgradeCode="$(var.UpgradeCode)" Name="$(var.ProductName)"
Language="!(loc.Language)" Codepage='1252' Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)">
<Package Id='*' Keywords='Installer' Description="My Installer" Manufacturer='$(var.Manufacturer)'
InstallPrivileges='elevated' InstallScope='perMachine'
InstallerVersion='200' Compressed='yes'/>
<MajorUpgrade Schedule="afterInstallValidate"
DowngradeErrorMessage="A later version of [ProductName] is already installed"
AllowSameVersionUpgrades="yes"
AllowDowngrades="no" />
<InstallUISequence>
<Show Dialog="WelcomeDlg" After="CostFinalize" />
</InstallUISequence>
</Product>
The problem is that I cannot seem to get upgrades and uninstalls to work with the same code/installer.
If I use Product Id="*", I'm able to perform upgrades, but when I try to uninstall, only the entry from Add/Remove Programs is removed. The installed files, however, remain in Program Files.
If I use Product Id="some random guid", I'm able to uninstall, but I'm no longer able to perform upgrades.
So my questions is:
Can I perform upgrades and uninstalls with a wildcard Id (i.e. Product Id="*"), or do I have to manually generate a new ID each time?
Thanks!
I used (Product Id="*") in my WiX installer and it is still able to perform upgrades and uninstalls. My code for Product, Package and Major Upgrade look almost identical to yours so I think the problem lies somewhere else.
Do you have this in your Product section to tell WiX which component groups to install/uninstall? (see code)
<Feature Id="ProductFeature" Title="[ProductName]" Level="1">
<ComponentGroupRef Id="ComponentGroup1" />
<ComponentRef Id="DesktopApplicationShortcut" />
</Feature>
Edit: I have since noticed one other thing that may help you out. I was recently having issues with my program not removing the Desktop Shortcut during Uninstall, despite it working in the past. I have since changed the Guid from "*" to a Guid code and it is now being removed. I think it is the program recognizing the Component.
<Component Id="DesktopApplicationShortcut" Guid="{Create Guid Code}">
I have a set of WiX scripts that used to allow me to create patches for patches, e.g. I would have full installers for the following version numbers:
11.00.38.01
11.00.38.02
11.00.38.03
I would then create patches between these numbers, i.e.
11.00.38.01-11.00.38.02
11.00.38.02-11.00.38.03
Using these scripts with WiX 3.0 I would be able to run
11.00.38.01
and then apply the
11.00.38.01-11.00.38.02 and 11.00.38.02-11.00.38.03 patches,
which would bring the installation up to
11.00.38.03
After upgrading to WiX 3.6 and later 3.7 and 3.8, this no longer works.
I can install one build and apply one patch to that build but I cannot install a build, patch the installation, and then apply another patch.
If I attempt to do that, I get the following error:
The upgrade patch cannot be installed by the Windows Installer service
because the program to be upgraded may be missing, or the upgrade
patch may update a different version of the program. Verify that the
program to be upgraded exists on your computer and that you have the
correct upgrade patch.
My patch template looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="no"
Manufacturer="Acme"
MoreInfoURL="http://www.acme.com/"
DisplayName="$(var.ProductName) $(var.ProductVersion) Upgrade"
Description="Minor Upgrade"
Classification="Update"
>
<Media Id="5000" Cabinet="RTM.cab">
<PatchBaseline Id="RTM"/>
</Media>
<PatchFamilyRef Id="$(var.ProductShortName)UpgradeFamily"/>
</Patch>
<Fragment>
<PatchFamily Id='$(var.ProductShortName)UpgradeFamily' Version='1.0.0.0' Supersede='yes'>
<ComponentGroupRef Id='PatchComponents' />
</PatchFamily>
</Fragment>
</Wix>
Part of the .wxs script for the product looks like this:
<Product Name='Acme Server'
Id='6DE00366-36D8-4BA0-B911-8FBD7490C472'
UpgradeCode='0FDE99AC-D910-46CF-814D-D851B81D3816'
Language='1033'
Codepage='1252'
Version='$(var.ProductVersion)'
Manufacturer='Acme'>
<Package
Id='*'
Keywords='Installer'
Description="Acme Server"
Comments='Acme Server is a registered trademark of Acme.'
Manufacturer='Acme'
InstallerVersion='200'
Languages='0'
Compressed='yes'
SummaryCodepage='1252'
Platform='x86'
/>
<Upgrade Id='0FDE99AC-D910-46CF-814D-D851B81D3816'>
<UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
Minimum='$(var.ProductVersion)' IncludeMinimum='yes' Maximum='$(var.ProductVersion)' IncludeMaximum='yes' />
<UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
Minimum='$(var.ProductVersion)' IncludeMinimum='no' />
</Upgrade>
</Product>
The interesting thing is that the WiX 3.0 patch log contains the following line:
PATCH SEQUENCER: verifying the applicability of minor upgrade patch
c:\Install\10.10.11.01-10.10.11.02\AcmeServer.msp against product
code: {6DE00366-36D8-4BA0-B911-8FBD7490C472}, product version:
10.10.1101, product language 1033 and upgrade code: {0FDE99AC-D910-46CF-814D-D851B81D3816}
whereas the WiX 3.6+ patch log contains this line:
PATCH SEQUENCER: verifying the applicability of QFE patch
c:\11.00.38.01-11.00.38.02\AcmeServer.msp against product code:
{6DE00366-36D8-4BA0-B911-8FBD7490C472}, product version: 11.00.3801,
product language 1033 and upgrade code:
{0FDE99AC-D910-46CF-814D-D851B81D3816}
Notice that the 3.0 log says "minor upgrade patch" whereas the 3.6+ log says "QFE patch". I do not know if this is relevant here.
What could I be doing wrong here? Why did the behavior of the generated patches change? Of course, there have been minor tweaks to the WiX scripts over the past couple of years but as far as I know none of them were related to the patching process. It seems as if the main change was due to the switch from WiX 3.0 to a newer version.
EDIT:
I have verified that this change happened exactly at the time I switched from WiX 3.0 to WiX 3.6.
I have also noticed that if I apply the WiX 3.0-generated patches, the version number is updated in Programs & Features when a patch is applied to a full installation or another patch whereas with the WiX 3.6+-generated patches, the version number stays the same when a patch is applied to a full installation.
I am wondering if any defaults have changed for the command-line tools (torch, pyro, etc)?
The solution was to add a ProductVersion property reference to the PatchFamily element as seen in the snippet below:
<Fragment>
<PatchFamily Id='$(var.ProductShortName)UpgradeFamily' Version='1.0.0.0' Supersede='yes'>
<PropertyRef Id="ProductVersion"/>
<ComponentGroupRef Id='PatchComponents' />
</PatchFamily>
</Fragment>
That was all there was to it.
I do not see this mentioned in any of the documentation or the usual, old sample patch script found on the web, though now that I know what to look for, it is easy enough to find discussions about it.
As I mentioned in my original question, this element was not necessary when using WiX 3.0 which might go some way to explain its absence from the old patch sample.
The following steps had been performed:
Setup1.msi had been built in VS2005 + WiX 3.0 (.NET Framework 2.0).
Version 1.0.0.0 had been installed by Setup1.msi.
For the purpose of minor upgrade a Setup2.msi had been built
(Setup2.msi differs from Setup1.msi ONLY in ProductVersion="1.0.1.0")
The following Patch.wxs had been prepared:
<Patch
AllowRemoval="no"
Classification="Update"
Comments="..."
Description="..."
DisplayName="..."
Manufacturer="..."
TargetProductName="...">
<Media Id="1000" Cabinet="MyPatch.cab">
<PatchBaseline Id="MyPatch" />
</Media>
<PatchFamily
Id="MyPatchFamily"
Version="1.0.1.0"
ProductCode="...THE SAME AS IN Setup1.msi..."
Supersede="yes">
<ComponentRef Id="CMP_Program_EXE" />
<ComponentRef Id="CMP_Desktop_Shortcut" />
<ComponentRef Id="CMP_ProgramMenu_Shortcut" />
</PatchFamily>
</Patch>
Patch.msp had been created with help of candle, light, torch and pyro.exe.
The following command had been invoked:
msiexec /p Patch.msp REINSTALL=ALL REINSTALLMODE=vomus
As a result, Program.exe was updated and new shortcuts "v. 1.0.1"
were created.
However, old Shortcut "v. 1.0.0" remained both on "DesktopFolder" and on
"ProgramMenuFolder".
How can I make the Patch remove old Shortcut?
Thanks in advance.
The simplest way is not to add version to shortcut name. See Windows UX Guidelines:
Avoid putting a version number in a program name unless that is how users normally refer to your program.
Otherwise your minor upgrade has to remove the shortcut to the old version and create a new shortcut that points to the new version.
During minor upgrade, the old version does not get uninstalled, that's why the shortcut is not updated.
You can use the RemoveFile element within the Component one owning the Shortcut:
<DirectoryRef Id="DesktopFolder">
<Component Id="..." Guid="...">
<Shortcut Id="..." Name="foobar_1.0.1" ... />
<RemoveFile Id="..." Name="foobar_1.0.0.lnk" On="install" />
...
</Component>
</DirectoryRef>
But. There's one problem remained -- when you uninstall you MSP patch, new shortcut (foobar_1.0.1.lnk) is not removed (because the Shortcut table is transformed back, I believe). Therefore, user ends up with two shortcuts. I do not know how to fix that, therefore I asked here.
Similiar question: Reusing WIX components to speed up candle/light
My project has the very same problem as the one referenced; a very large static database that never changes is compressed into the msi every time a build is required. I would like to do as the question asks: reuse a pre-compressed cab file to speed up the build time.
I started doing as the answer suggests, using the cabCache property. I added the following to the .wixproj:
<CabinetCachePath>cabs</CabinetCachePath>
<ReuseCabinetCache>True</ReuseCabinetCache>
I then seperated the static data into a fragment:
<Fragmet>
<Media Id="2" Cabinet="static.cab" EmbedCab="no" />
<Component Id="staticCab" Guid="..." >
Files ...
</Component>
And the fragment was referenced in the feature:
<ComponentRef Id="staticCab" />
This created the cab file, but left it empty. My next thought was the use a Merge Module. I created the module:
<Module Id="StaticModule" Language="1033" Version="1.0.0.0" >
<Package ...>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="MergeRedirectFolder" Name=".">
<Component Id="StaticFiles" Guid="...">
Files...
</ -- End all XML Tags
And then merged it:
<Directory Id="StaticDir" Name="static">
<Merge Id="StaticModule" Language="1033" src="..\Static\bin\Release\static.msm" />
</Directory>
<Feature ...>
<MergeRef Id="StaticModule"/>
</Feature>
Even after all this, the CabinetCache is still being rebuilt every time.
I guess my question would be what is the correct way to use ReuseCabinetCache. I'm still learning WIX, so I apologize if the answer is evident. I just am not sure how to use it.
Edit: A MergeModule would not be ideal since there is no need to share that logic with other msi's. It is only useful to this single project to a single development team.
I'm going to go ahead and answer my own question since it turned out to be so simple.
Change the .wxiproj to have these properties in
<CabinetCachePath>cabs</CabinetCachePath>
<ReuseCabinetCache>True</ReuseCabinetCache>
Add a media to the .wxs install
<Media Id="2" Cabinet="static.cab" EmbedCab="yes" />
In the Directory tag where you store the static files, add DiskId="2".
This will do a couple of things. First you are telling Wix that you wan't to store the cabinets in a path to reuse the cabinets. Creating a new cabinet and only storing static data in it (or data that doesn't change often) will cause Wix to use the cached version of the cabinet. Wix validates the cabinets by ensuring that:
The number of files in the cached cabinet matches the number of files being built.
The names of the files are all identical.
The order of files is identical.
The timestamps for all files all identical.
(Source: http://wix.sourceforge.net/manual-wix3/optimizing_builds.htm)
No wonder I couldn't find any documentation on it. Its so easy to do it should have been apparent to me.
Update: Also, multiple threads are used to build multiple cabinets. Creating multiple cabinets will improve the speed even more.
We have the multiple MSI's for the different languages, so each MSI has its own ProductCode and UpgradeCode. Using English MSI's, we created a patch using Aaron's approach in http://blogs.msdn.com/astebner/archive/2007/10/26/5700191.aspx, e.g. candle / light / torch / pyro
with the following Patch.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="yes"
Manufacturer="xxx"
MoreInfoURL="xxx"
DisplayName="MyProduct First Patch"
Description="My Product First Patch"
Classification="Update Rollup"
>
<Media Id="5000" Cabinet="RTM.cab" >
<PatchBaseline Id="RTM"/>
</Media>
<PatchFamilyRef Id="PatchFamilyRollup"/>
</Patch>
<Fragment>
<PatchFamily Id='PatchFamilyRollup' Version='1.1.1.1' Supersede='yes'>
...
However, when we apply this patch on the machine where non-English MSI was installed, we get the following error:
"The upgrade patch cannot be installed by the Windows Installer service because the program to be upgraded may be missing, or the upgrade patch may update a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade patch."
So my question is,
is it possible to create a patch (MSP) that can be used on any language?
If so, what needs to be done?
I think you should experiment with the Validate element, which is a child of PatchBaseline, and the validation flags of torch.exe command line. The right combination of bits will let you install your patch.
Thanks Yan for giving me a right direction. I played with "Validate" element and "torch" command quite a few hours, but I got the same error. Then my co-worker showed me "TargetProductCode" element. After a few trials, I finally made it work although the solution isn't purely language-neutral. The answer I found is a combination of "Validate" element and "TargetProductCode" element. I am posting my own answer so that someone may get benefit out of it.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="yes"
Manufacturer="xxx"
MoreInfoURL="xxx"
DisplayName="MyProduct First Patch"
Description="My Product First Patch"
Classification="Update Rollup"
>
<Media Id="5000" Cabinet="RTM.cab">
<PatchBaseline Id="RTM" >
<Validate ProductId='no' ProductLanguage='no' ProductVersionOperator='LesserOrEqual' UpgradeCode='no' />
</PatchBaseline>
</Media>
<TargetProductCodes Replace='yes'>
<!-- list all language specific ProductCode here. -->
<TargetProductCode Id='{xxxxx}' /> <!-- ProductCode for English -->
<TargetProductCode Id='{yyyyy}' /> <!-- ProductCode for French -->
</TargetProductCodes>
<PatchFamilyRef Id="PatchFamilyRollup"/>
</Patch>
...