I'm testing out the MSIX features of the WiX framework. When I attempt to build I receive the following error:
light.exe(0,0): error LGHT0221: The definition for the
'FgExcludeDarwinFeatures' table's 'Feature_' column is a foreign key
relationship to the 'Feature' table's column number 1. The
modularization types of the two column definitions differ: one is
Column and the other is None. Change one of the modularization types
so that they match.
My setup:
Followed installation instructions from: https://www.firegiant.com/wix/wep-documentation/getting-started
Created a default wix setup project in visual studio 2019. Included FgMsixExtension.wixext.dll, included the fgmsix.xsd property on Wix element.
I'm running toolset v3.11.2.4516 (latest). Expansion Pack v3.11.476 - 2020-12-22 (latest)
Project compiles fine without the MSIX line, and the inclusion of the FgMsixExtension.wixext
Any ideas what I am missing?
Also does anyone have a working WiX msix example I can also compare to?
Just in case it is needed, here is a very quick edit of the default setup project from a wix template:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:fga="http://www.firegiant.com/schemas/v3/wxs/fgmsix.xsd">
<Product Id="*" Name="SetupProject3" Language="1033" Version="1.0.0.0" Manufacturer="test1" UpgradeCode="77c4b832-ed73-4ba2-825c-7eee7837a8f4">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<fga:Msix Id="testy" Publisher="CN=test1" Target="desktop" />
<!--<fga:Application Id="MyApp" ExecutableFile="prodFile" />-->
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="test.cab" EmbedCab="yes" />
<Feature Id="ProductFeature" Title="SetupProject3" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject3" />
</Directory>
</Directory>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<Component Id="ProductComponent">
<File Id="prodFile" Source="C:\Program Files (x86)\WiX Toolset v3.11\bin\FireGiant.LicensingTool.exe" />
</Component>
</ComponentGroup>
</Product>
</Wix>
Just finished a conversation with FireGiant Support. This was due to a bug:
The dev team published the fix in v3.11.479. This should solve the issue you faced.
Let us know if you have any other questions or problems.
Happy packaging!
-- FireGiant Support
v3.11.479 released 01/15/2021
Related
I'm trying to create an installer using WiX for an add-in to a product called SolidWorks.
Looking at the docs led me to believe that I should be able to look up a location based on a registry value to find the install destination.
Here is the registry value I'm trying to target:
As seen in the picture it is located at HKEY_LOCAL_MACHINE\SOFTWARE\SolidWorks\SOLIDWORKS 2022\Setup\SolidWorks Folder.
I've tried to follow the instructions and have tried many iterations, with the following being the latest.
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SolidWorks Add-In" Language="1033" Version="1.0.0.0" Manufacturer="My Company" UpgradeCode="073e3b99-1977-4a3e-a4dc-0d61cc6ddbee">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Description="SolidWorks Add-In Installer" Manufacturer="My Company" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Feature Id="ProductFeature" Title="Installer" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<Property Id="MsiLogging" Value="v" />
<Property Id="SOLIDWORKSDIR">
<RegistrySearch Id="SolidWorksRegistry" Type="raw" Root="HKLM" Key="SOFTWARE\SolidWorks\SOLIDWORKS 2022\Setup" Name="SolidWorks Folder" />
</Property>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="SOLIDWORKSDIR" Name=".">
<Directory Id="My_Company" Name="My Company">
<Directory Id="INSTALLFOLDER" Name="SolidWorks Add-In" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="AutofacLibrary" Guid="3124c97d-079d-48fe-bc7c-e594bf49ae4a">
<File Id="AutofacDLL" Name="Autofac.dll" DiskId="1" Source="..\SolidWorksAddIn\bin\Release\Autofac.dll" KeyPath="yes" />
<File Id="AutofacPDB" Name="Autofac.pdb" DiskId="1" Source="..\SolidWorksAddIn\bin\Release\Autofac.pdb" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
This seems to completely ignore the registry value though and the install location is C:\My Company\SolidWorks Add-In
I can't figure out what needs to change. How am I targeting the registry value incorrectly or referencing the property incorrectly that isn't allowing the installer to place the installed files in the directory I want them to be in?
As per the comments above, the issue is that the registry key is in the 64-bit hive but the package was 32-bit. The fix is to either make the package 64-bit (so the searches look in 64-bit locations by default) or make the registry search 64-bit by adding the Win64='yes' attribute.
I've followed the official Major Upgrade guide and I seem to be missing something.
Here is my MCVE:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Codepage="1252" Language="1033" Manufacturer="Bla Corporation"
Name="Bla" UpgradeCode="PUT-GUID-HERE" Version="31.00.0000">
<Package Comments="Contact: Refael Sheinker, refael.sheinker#bla.com." Description="Bla"
InstallerVersion="500"
Compressed="yes"
InstallScope="perMachine"
Keywords="Installer,MSI,Database" Languages="1033" Manufacturer="Bla Corporation" Platform="x64" />
<Media Id="1" Cabinet="my_application.cab" EmbedCab="yes" />
<MajorUpgrade AllowDowngrades="no"
AllowSameVersionUpgrades="no"
Disallow="no"
IgnoreRemoveFailure="no"
MigrateFeatures="yes"
Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed" />
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONROOTDIRECTORY" />
<UIRef Id="WixUI_InstallDir" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="PROGRAMFILESSUBDIR" Name="Bla">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="BlaInternal" />
</Directory>
</Directory>
</Directory>
<DirectoryRef Id="APPLICATIONROOTDIRECTORY">
<Component Id="tenlira.ini" Guid="*">
<File Id="tenlira.ini" Source="..\ConfigurationFile\x64\tenlira.ini" KeyPath="yes" />
</Component>
</DirectoryRef>
<Feature Id="MainApplication" Title="TenLira" Level="1">
<ComponentRef Id="tenlira.ini" />
</Feature>
</Product>
</Wix>
All it does is simply installing a single file as an example. So far, so good. Now, all I do is add another Component and File and off course the corresponding ComponentRef in Feature. I specifically leave the Version as is: 31.00.0000. What I expected is that the new installer will not perform a Major Upgrade, but it does. Why? Also, there is now 2 entries in Add/Remove Programs.
Please help me find out what am I missing here. Thanks. Refael.
UPDATE:
Posting the question got me to reread the documentation again and I discovered that the AllowSameVersionUpgrades thingy in the MajorUpgrade element should be set to yes. This time there is only one entree in the Add/Remove Programs, but it still performs Major Upgrade. Why?
UPDATE: Here is a list to help debug failing major upgrades by identifying the most common problems: Common causes of failed major upgrades
Major Upgrade - "The Old, Manual Way"
I guess you are hitting an oddity that may not be handled entirely as expected by the WiX MajorUpgrade element by combining the auto-generated product GUID, the AllowSameVersionUpgrades set to yes and keeping the version number the same.
I can't see any obvious way to set the MinInclusive attribute in WiX's MajorUpgrade element - I could be mistaken, there might be a way I am unaware of. For what it is worth, I am not too keen on allowing "same version upgrades".
However, you could try to "use the old way" to author the Upgrade table using the "older elements" Upgrade and UpgradeVersion. The MajorUpgrade element is essentially a "convenience" feature to set up your major upgrades easily, and I believe it works for most users. Bob Arnson has a blog explaining the introduction of the MajorUpgrade element. This blog also shows a sample of how to do things "manually" with the "older elements" Upgrade and UpgradeVersion (do check it out).
I made a quick mock-up that might do what you want, it is just a "rough draft" - can't make any guarantees. I use preprocessor defines to set some variables that can be referenced in the WiX source file - as a C++ developer this is a piece of cake for you so I won't waste time explaining it - the source should make sense:
<?define MyProductVersion = "31.00.0000" ?>
<?define MyProductCode = "PUT-GUID-HERE" ?>
<?define MyUpgradeCode = "PUT-GUID-HERE" ?>
<!--Recommendation: set a path variable that you can redirect at will to a new release folder (new build output folder): -->
<!-- <?define MyBasePath = "C:\Projects\MyApp\Release\31.00.0000\" ?> -->
<!-- SAMPLE:
<Component Win64="yes" Feature="MainApplication">
<File Source="$(var.MyBasePath)\myapp.exe" />
</Component> -->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="$(var.MyProductCode)" Codepage="1252" Language="1033" Manufacturer="Bla Corporation"
Name="Bla" UpgradeCode="$(var.MyUpgradeCode)" Version="$(var.MyProductVersion)">
<Package Comments="Contact: Refael Sheinker, refael.sheinker#bla.com." Description="Bla"
InstallerVersion="500"
Compressed="yes"
InstallScope="perMachine"
Keywords="Installer,MSI,Database" Languages="1033" Manufacturer="Bla Corporation" Platform="x64" />
<Media Id="1" Cabinet="my_application.cab" EmbedCab="yes" />
<!-- Major upgrade -->
<Upgrade Id="$(var.MyUpgradeCode)">
<!-- Downgrade Protection -->
<UpgradeVersion Minimum="$(var.MyProductVersion)" OnlyDetect="yes" IncludeMinimum="yes" Property="DOWNGRADE_DETECTED" />
<!-- Major Upgrade Configuration -->
<UpgradeVersion IncludeMinimum="no" Maximum="$(var.MyProductVersion)" IncludeMaximum="no" MigrateFeatures="yes" Property="UPGRADE_DETECTED" />
</Upgrade>
<!-- Major Upgrade: Schedule RemoveExistingProducts -->
<InstallExecuteSequence>
<!-- Potential scheduling (after): InstallValidate, InstallInitialize, InstallExecute, InstallExecuteAgain, InstallFinalize -->
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
<!--Launch Condition: Abort setup if higher version found-->
<Condition Message="!(loc.NewerVersionDetected)">
NOT DOWNGRADE_DETECTED
</Condition>
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONROOTDIRECTORY" />
<UIRef Id="WixUI_InstallDir" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="PROGRAMFILESSUBDIR" Name="Bla">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="BlaInternal" />
</Directory>
</Directory>
</Directory>
<DirectoryRef Id="APPLICATIONROOTDIRECTORY">
<Component Id="Test.ini" Guid="PUT-GUID-HERE" Win64="yes" Feature="MainApplication">
<CreateFolder Directory="APPLICATIONROOTDIRECTORY" />
<IniFile Id="SomeSetting" Action="addLine" Directory="APPLICATIONROOTDIRECTORY" Key="Setting1" Name="Test.ini" Section="MySection" Value="Some Setting" />
<IniFile Id="OtherSetting" Action="addLine" Directory="APPLICATIONROOTDIRECTORY" Key="Setting2" Name="Test.ini" Section="MySection" Value="Other Setting" />
</Component>
</DirectoryRef>
<Feature Id="MainApplication" Title="TenLira" Level="1">
<!--<ComponentRef Id="tenlira.ini" />-->
</Feature>
</Product>
</Wix>
Now the !(loc.NewerVersionDetected) has to be explained. This is a localized string (for delivering your setup in different languages). To use it, right click your WiX project in Visual Studio and go: Add New Item... => Localization File => Add. As the localization file is added, your output MSI will also now go into a en-us folder under your main output location (Debug or Release).
In the localization file, add:
<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="NewerVersionDetected">A later version of [ProductName] is already installed.</String>
</WixLocalization>
And you should now be able to add new strings to this file and easily translate your whole setup using such language files.
Also add the WiX GUI extension. Right click "References". Add Reference... => Browse to WixUIExtension.dll => Double click this file, and press OK. Normal folder to find the file is: C:\Program Files (x86)\WiX Toolset v3.11\bin.
INI-Files
I just want to mention that INI files should ideally be installed via the IniFile table (entries are treated as atomic key-value pairs allowing advanced merging of keys and values for existing INI files), and not via the File table (the file is treated as a regular file either overwriting the whole existing file or leaving it in place - not enforcing any new values). The WiX element corresponding to the MSI IniFile table is naturally the IniFile element.
An ad-hoc sample:
<Component Id="Test.ini" Guid="PUT-GUID-HERE" Win64="yes" Feature="MainApplication">
<CreateFolder Directory="APPLICATIONROOTDIRECTORY" />
<IniFile Id="SomeSetting" Action="addLine" Directory="APPLICATIONROOTDIRECTORY" Key="Setting1" Name="Test.ini" Section="MySection" Value="Some Setting" />
<IniFile Id="OtherSetting" Action="addLine" Directory="APPLICATIONROOTDIRECTORY" Key="Setting2" Name="Test.ini" Section="MySection" Value="Other Setting" />
</Component>
Links:
Adding entries to MSI UpgradeTable to remove related products
It does a major upgrade because both MSIs have the same UpgradeCode and you have now specified AllowSameVersionUpgrades, so it does the upgrade where it didn't before.
Your build generates a new ProductCode every time, so each MSI is a new product, so you will get it installed twice if it doesn't do an upgrade and once if it does. You may have some assumption about the way upgrades work that you haven't spelled out.
I had the same problem where Version is same, but the Id is different creating multiple entries in Add/Remove programs.
My simple fix was to set AllowSameVersionUpgrades="yes".
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of $(var.ServiceName) is already installed." />
I've tried most of the answers on the topic in this forum and other forums, but I still have this problem.
I want to update a bundle version and when I build and install the installer, it should upgrade a previous installation and not create two records in "Programs and Files".
I'm using the following code in Product.wxs.
<Product Id="*" Name="SetupProject1" Language="1033" Version="1.0.0.0" Manufacturer="miro" UpgradeCode="5ba49b49-25c4-47c0-82da-12bf5310af58">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade AllowDowngrades="no" AllowSameVersionUpgrades="yes" IgnoreRemoveFailure="no" DowngradeErrorMessage="loc.NewerVersionInstalled" Schedule="afterInstallInitialize"/>
<MediaTemplate />
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<Component Id="ProductComponent">
<File Id="file_Exefile" Source="..\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe">
</File>
</Component>
</ComponentGroup>
</Fragment>
I am even considering writing my own update logic based on the Installer Processes and their ProductVersion properties, but there are too many cases to consider.
Can you tell me what is wrong with this Product.wxs ,so I can fix it.
Thanks.
Best regards,
Evgeni Dyulgerov
There are several things that could be preventing a major upgrade. You appear to have the correct MajorUpgrade logic, but:
It would be better if you incremented your product version in the first three fields, that's more normal for a major upgrade.
It's not obvious that your current UpgradeCode is the same as the older product's, so check that it is.
If the previous product's install scope was perUser the major upgrade will not work because cross-context major upgrades aren't allowed by Windows Installer.
Do the install taking a verbose log and look at all occurrences of FindRelatedProducts. There will be more than one, but see if the one in the upgrade install finds a previously installed product.
You have to add an upgrade section to your product section.
<Upgrade Id='5ba49b49-25c4-47c0-82da-12bf5310af58'>
<UpgradeVersion OnlyDetect='no' Property='ISUPGRADE'
Minimum='0.0' IncludeMinimum='yes'
Maximum='1.0.0.0' IncludeMaximum='no' />
</Upgrade>
Checkout Upgrades and Modularization on Firegiant
Also the WiX Documentation chm (in your Start Menu) is very helpful.
I am trying to create an installer for a simple .NET WPF C# app. I am using VS 2013, and WiX 3.10.2. Following the steps in the Wix Tutotial/ .NET/ Bootstrapping I have created a Boostrap.exe which chains .NET web installer and the app Setup.msi.
EDIT: My goal is to understand how to configure the WiX Bootstrap and Setup projects for small updates, minor upgrades, and major upgrades scenarios.
Out of the box, everything seems to work nice when I run a fresh install. However, when I run a fresh built Bootstrap.exe over an already existing installation a duplicate entry appears in the Apps & features and no file is changed in the app target location - contrary to the expectation that the same entry should remain in the Apps & features and the target location should be updated. EDIT: Looks like there may not be a way to change REINSTALLMODE?
If I add a Product Id and then change the version of the Setup (minor upgrade), the Bootstrap fails with User cancelled installation? The log file shows "Error 0x80070642: Failed to perform minor upgrade of MSI package." EDIT: Inside the MSI log a SecureRepair fails with error code 39439E438 (?) probably because the stored hash value does not match the current... but that should be expected in a minor upgrade MSI, right?
Are there recommended configurations between the Boostrapper and Setup WiX projects such that the small update, minor upgrade, and major upgrade use cases can be handled properly, or does the WiX Bootstrapper support ONLY major upgrades?
I will continue to investigate and I'll post updates to my findings;
Any hints are greatly appreciated,
Thanks!
Here are the source files which I barely changed from the WiX wizard generated code:
--- Product.wxs ---
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SetupProject1 1.0.0.0" Language="1033" Version="1.0.0.0" Manufacturer="Acme" UpgradeCode="4c8a8cbf-e3d0-410c-8a8d-7e67eb4e7ff7">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" InstallPrivileges="limited" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="AcmeFolder" Name="Acme">
<Directory Id="INSTALLFOLDER" Name="WpfApplication1" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent" Guid="8CA0B70F-39DA-4B4B-9104-46C58E26FCF4">
<CreateFolder/>
<RemoveFolder Id="RemoveAcmeFolder" Directory="AcmeFolder" On="uninstall"/>
<RemoveFolder Id="RemoveINSTALLFOLDER" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\Acme\WpfApplication1" Name="Version" Type="string" Value="[ProductVersion]" KeyPath="yes" />
<File Source="$(var.WpfApplication1.TargetPath)" KeyPath="no" />
</Component>
</ComponentGroup>
</Fragment>
--- Bundle.wxs ---
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="Bootstrapper1 1.0.0.0" Version="1.0.0.0" Manufacturer="Acme" UpgradeCode="e1092cbb-9134-42fc-a9f2-652f95f361fd">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage Name="Acme Setup" SourceFile="$(var.SetupProject1.TargetPath)" Vital="yes" />
</Chain>
</Bundle>
If you change your executables, increase their version numbers. Windows Installer assumes files with the same versions are the same.
To upgrade an .msi package, increase its version number either as part of a major upgrade (typical) or minor upgrade.
To upgrade a bundle, increase its version number. By default, Burn keeps bundles with the same version installed.
I have a very simple setup project:
<Product Id="*" UpgradeCode="$(var.UpgradeCode)" Name="$(var.ProductLongName)" Language="1033"
Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)">
<Package InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<!-- Installation Parts -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="WindowsFolder">
<Component Id="ProductComponent" Guid="b3250107-4859-4d5f-857c-1756af65ec32">
<File Id='SomeFile' Name='SomeFile.scr'
Source='SomeFile.scr' Vital='yes' />
<!-- Other files -->
</Component>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="$(var.ProductShortName)" Level="1">
<ComponentRef Id="ProductComponent" />
<!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->
<ComponentGroupRef Id="Product.Generated" />
</Feature>
<!-- Prerequisites -->
<PropertyRef Id="NETFRAMEWORK40CLIENT"/>
<Condition Message="This application requires .NET Framework 4.0. Please install the .NET Framework then run this installer again.">
<![CDATA[Installed OR NETFRAMEWORK40CLIENT]]>
</Condition>
</Product>
It installs ok and uninstall seem to finish ok too, but all files remain. They are not deleted.
Any ideas?
So, this problem is gone when I changed component guid to a freshly generated. Don't really understand why. Weird.
The component GUID in the OP was all in lower case. By convention MSI prefers GUIDs to be all in upper case just in case you need to pass the GUID across the service boundary as a (public) property. Was your new GUID all in upper case, by any chance?