Wix ICE32: Possible Mis-Aligned Foreign Keys - wix

When adding a merge module (Visual FoxPro Oledb V9) to a wix project, I get the following error message:
error LGHT0204: ICE32: Possible Mis-Aligned Foreign Keys
Using WiX Toolset v3.11
I get no indication of the table in which the keys are misaligned from the output.
I have tried opening the vfpoledb.msm in Orca, but I can't seem to find anything that looks like it is mismatched in terms of field sizes.
The merge module is being included with:
<Directory Id="TARGETDIR" Name="SourceDir">
<Merge Id="VFPOleDb" SourceFile="$(var.resources)\vfp-ole-db-merge-module\vfpoledb.msm" DiskId="1" Language="0"/>
...
</DirectoryRef>
<Feature Id="MainApplication"
Title="Application Title"
Level="1"
ConfigurableDirectory="INSTALLDIR"
Absent="disallow">
<MergeRef Id="VFPOleDb" />
<ComponentGroupRef Id="MainComponents" />
<ComponentGroupRef Id="ShortcutComponents" />
</Feature>
This merge module was previously included in an InstallShield installer project with no apparent issues. I've since converted across to using Wix but can't seem to get the installer to build with this merge module included (other merge modules are included e.g. vc++ runtime).
I can confirm that removing the merge module from the xml with no other modifications then allows the installer to build (removing the Merge and MergeRef elements for the merge module).
I've searched the internet to try and find suggestions to resolve this, with the only page I can find suggesting adjusting the table schema using Orca, but as mentioned, I get no further info on what table is causing the problem.
Any advice appreciated on how to either resolve the issue, elicit more information as to the offending table within the .msm.

Build from the command line and you'll get the misalignment(s). Visual Studio won't show multiple lines for a single error.

Run validation on the built MSI to see which tables are effected then use the EnsureTable element to tell WiX to put this empty table in. This will happen prior to merging of the merge modules and will make the error go away.

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.

INI disappear & NeverOverwrite="yes"

I have following problem : a new version disappears after upgrade, although I set NeverOverwrite='yes'. Could anyone help me about this issue?
<Feature Id="CompRef03" Title="CompRef" Level="1">
<Component Id="INIWindowsFolder" Directory="WindowsFolder" Guid="d09921c0-1192-458f-8a3e-88889f56a013" KeyPath="yes" NeverOverwrite="yes" Permanent="yes">
<File Id="test.INI" Source="test\intest.INI"/>
</Component>
</Feature>
Problem: Not sure exactly what has happened here. You don't set REINSTALLMODE=amus, do you? Maybe you have changed the component GUID from version 1 of your package? (component GUIDs must remain stable between versions for reference counting to work correctly). Or else the file could be uninstalled and reinstalled (should not happend when you set a file permanent, but maybe you forgot that in your first package).
IniFile Element: Ini files are actually not supposed to be installed as files, but as "change items" of INI value pairs. In other words you define what entries inside the file should be added, changed, removed, etc... In Wix you use the IniFile Element to achieve this. All merge capabilities, rollback support and advanced ini file handling come along for free. All you need to do is to define what needs to be added or modified in the ini file during your installation. It will also be created if it is not there in the first place. Please find more details in this answer. And here is one more link to IniFile Element usage.

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.

Conditional inclusion of files based on an Environment variable in a WIX file

So I have a deployment project based on WIX. I notice that you can include features and files in there. However I only want to deploy a particular file if the DEV/QA environment is selected. If they select Production I want it to ignore this particular file.
Is there a way in the .wxi file to conditionally include a feature / directory & files based on a particular value of a variable?
ie. I want to have something like the below - potentially the componentRef included dynamically? (I have sanitised the values).
<Feature Id="MyApplication" Title="MyApp" Description="My Application" ConfigurableDirectory="MYAPP" Level="1">
<ComponentRef Id="AppEmailTemplatesDir" />
</Feature>
and then further down
<Directory Id="EmailTemplatesDir" Name="EmailTemplates">
<Component Id="AppEmailTemplatesDir" Guid="{A-GUID}">
<File Id="EmailTemplate1.htm" Name="EmailTemplate1.htm" DiskId="1" Source="..\..\EmailTemplates\EmailTemplate1.htm" />
</Component>
</Directory>
Any ideas? We do have custom Actions code (VB.NET) but I'm not sure how that could be used apart from writing code to include files.
There seem to be a variety of ways to do this ... this is what worked for me in Visual Studio 2013.
In the WiX project Properties / Tool Settings add this to Additional parameters / Compiler::
-dReleaseType=$(ReleaseType)
Create a component group containing only the additional file (this is left as an exercise for the reader)
In the main .wxs file add something like this where PDBFile is the id of the component group in step 2:
<!-- Installs a PDB file for daily builds -->
<?if $(var.ReleaseType) = daily ?>
<ComponentGroupRef Id="PDBFile"/>
<?endif?>
Run devenv to build the WiX project with ReleaseType set in the environment
Looks like I can use a Component NeverOverwriteOption="yes" option to ensure the installer doesn't overwrite the files when they exists.
Unless the environment conditional stuff was easy to figure out - this seems to achieve what I need which is to not overwrite the file on production.
I also found that on uninstall it was deleting all the folders (as expected) but to keep the template path I could use the Permanent="yes" attribute.
After discussion we've decided to keep all the files in source control and deploy them. But at least I learnt about NeverOverwriteOption and Permanent :)

wix setup does not install VS 2005 merge module files

it might be a stupid question, but i've spent few hours testing various possibilities and didn't find the answer.
I have one standard merge module prepared in VS 2005 (its probably fine, i've prepared standard VS 2005 setup project, included the merge module and it worked properly)
Wix project(mainly because GUI reasons) to take care about the installation. Code samples(shortened for brevity)
Directories part:
<Directory Id="INSTALLLOCATION" Name="sth">
<Merge Id='MyModule3' Language='1033' SourceFile='MergeModule.msm' DiskId='1' />
</Directory>
Feature part:
<Feature Id="ProductFeature3" Title="Tit" Level="1" Description='Yeah' ConfigurableDirectory='INSTALLLOCATION' Display='expand'
AllowAdvertise='no'>
<MergeRef Id='MyModule3' />
<ComponentGroupRef Id="Product.Generated" />
</Feature>
After building WIX project it throws errors like:
ICE83: Both MsiPublishAssemblies AND MsiUnpublishAssemblies actions MUST be present in InstallExecuteSequence table.
ICE83: The MsiPublishAssemblies action MUST be present in AdvtExecuteSequence table.
I've added lines:
<InstallExecuteSequence>
<Custom Action="PreventDowngrading"
After="FindRelatedProducts">NEWPRODUCTFOUND</Custom> //i suppose it doesnt influence nothing here
<MsiPublishAssemblies Sequence="1502" />
<MsiUnpublishAssemblies Sequence="1501" />
</InstallExecuteSequence>
And:
<AdvertiseExecuteSequence>
<MsiPublishAssemblies Sequence="1502" />
</AdvertiseExecuteSequence>
After that buildling process doesn't return any errors, but despite installing the feature (selected on feature list) there are no feature files on the HDD. I think it might be caused by Sequence numbers but i haven't got any ideas how to fix them, anyone can help?
If more info is needed i'll surely provide it.
I can think of a number of things that can go wrong. I'd look at the install log to see if the files got installed, just not where you were expecting them to get installed. I've known VDPROJ MSM's to have a great many problems including authoring their directory tables incorrectly.
You might want to look at an open source project that I created called IsWiX (CodePlex.com). It's designed be a UI authoring tool for WiX Merge Module projects that also allows you the raw ability to add additional metadata using traditional WiX XML. The result is a very clean merge module that can be consumed by InstallShield, WiX, VDPROJ, et al.