wix installer ice03 Invalid Language Id - wix

I have a night build which runs on different machine then mine
on my machine i can compile the installer and use the msi without a problem
however on the night build machine i get
C:\Builds\73\Tools\AppInstaller\src\AppInstaller\APPExportReleaseDir.wxs (693): ICE03: Invalid Language Id; Table: File, Column: Language, Key(s): filAAED19CB2C0BBE304CDB8EB1AAF7473F
The file which is showing that is system.windows.interactivity.xml
Can you please explain what are ICE03 errors and how can I fix this ?
It says here to remove the Language or set it to "0"
http://softwarepackaging.co.uk/iceerrors but there is no explanation.

ICE rules are Internal Consistency Evaluators - essentially a series of self-diagnosis scripts checking database
referential integrity, database consistency, data type and schema
compliance as well as running several content validation tests or
logical tests on the whole MSI (which is really an MS-SQL database in disguise).
DB Integrity: In other words you check the content of the database against the database schema and a number of content validation rules and determine if the database is objectively speaking containing what it is supposed to, and that it is connected in correct ways.
Sanity-Checks: Some further checks move beyond simple schema and type checking and perform sanity-checks relating to how the application is actually being installed. Certain files should not go to certain locations, some registry keys should never be written to, and similar checks. Custom checks can be created and added as QA steps for corporate deployment.
Custom Actions: The checks are written as custom actions (essentially MSI's mechanism for running executable, custom installation logic during installation) and inspect and evaluate the database during a Validation run. The Windows SDK tool Orca is capable of running validation on any MSI file as illustrated in this picture:
ICE3: Your particular error message relates to ICE03 - it checks several different things, but this checkpoint is relevant here (please visit the link to see what else it checks):
Invalid Language Id - The database contains an invalid numeric Language Identifier (LANGID). See the Language data type. See Language Identifier Constants and Strings. For example, 1033 for the U.S. and 0 for language neutral.
In your case you need to remove the language specifier altogether if the file is language neutral, or fix your WiX source file to set an appropriate language code. Here is an example from the MSI file installing Orca (1033 is English, most files are unspecified, meaning they are language neutral):
Links:
Wix Custom Dialog Error : ICE03: Not a valid foreign key Visual Studio 2019
WIX Error - ICE03: Not a valid foreign key
ICE03: String overflow (greater than length permitted in column); Table: CustomAction
https://learn.microsoft.com/en-us/windows/win32/msi/ice03
WIX Toolset 3.11: Including es-419 language DLLs gives ICE03 error. (.NET 4.8)

Do you really even need to include that file in your MSI? Typically xml files with the name of the assembly are just useful to developers as SDK documentation and doesn't belong in a shipped product.
For that matter, did you even author the wxs or are you using some form of dynamic authoring at build time? If so, add this to my list of reasons of why this is an anti-pattern. (Don't worry, almost no one else wants to believe me either. )
For more information on ICE's ( basically unit tests ) see:
MSI Tip: Authoring an ICE using C# / DTF

Related

Is there a way to set a property value to the formatted install date/time

Is there a way to set a property value to the formatted install date/time?
I'm in the process of creating an MSI installer for an old VB6 application we still depend on (yes, I know, upgrade before it dies).
I'm trying to add a backup folder for the user data files in the install-folder (not my application design, nor my application). Unfortunately every user of this application has their own copy of the data file installed on their system (dedicated machines per user), and the installer has the default file. I would like to create a backup folder so that I can manually (if necessary) go back and retrieve previous versions of the file.
What I'm thinking is
c:\program files (x86)\app*.mdb => c:\program files (x86)\app\backups\201804091125
This will be rushed. Please tell me what is not clear.
Custom Action: In order to implement exactly what you describe, you generally need a custom action. This is always unfortunate since they are very error prone: Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?
Alternative?: If you ask me I would install the database in a component of its own, make the file the key file and set the component to permanent and never overwrite if key path exists.
In the WiX source: for the WiX component element, set these attributes: Permanent="yes" NeverOverwrite="yes"). I am not 100% sure what will happen if you do something stupid such as setting REINSTALLMODE="amus" during installation (force overwrite all files regardless of version). It has been a while since I tested the NeverOverwrite flag. But for normal deployment done the regular way the database file should be left alone and not overwritten.
Custom Action Overview: There are properties called Time and Date that are automatically set in the installer, but the Date property will generally contain characters that are illegal in path names. It is possible to just get the properties and replace the illegal characters. However, the date separation characters are probably different based on regional settings and hence hard to predict. Your code could get messy quickly and testing would be challenging (potentially many locales to test depending on distribution scope - a truly globally capable package is challenging).
I would rather get the date and time some other way - via some programming API call where I can determine what format the data comes back in. You also need to run this custom action elevated in deferred mode to ensure it doesn't fall over with access denied (insufficient user rights for operation). This is always quite a bit of clunk to set up and get working. Maybe try the alternative approach first?
I have long considered adding a custom action to abort the install if REINSTALLMODE="amus" has been specified. I would prefer that and the alternative approach described with "never overwrite" to a custom action doing all this copying.

WIX get substring from variable

As part of my WIX setup project, I am updating some values in the app config for the service I am installing. One of the attributes is a number, this is the number of the location the service is being installed at.
The location is part of the machine name, for example the machine name might be "location16server". I am trying figure out if I can get a substring or otherwise parse the number out of the machine name so that I may use it to update the .config file. I don't see any ways that are part of WIX, but maybe with a custom action?
Thanks
A custom action would be required. I'd provide caution on this though as you are tightly coupling along a machine name. This might work well in a controlled environment but could cause major headaches down the road. I'd look for some other artifact on the machine to determine location numbers and other configuration data. Perhaps even move it out of the installer and into the application if possible.
Another option is to insert a dialog box that allows the user to enter some optional parameters for the program being installed.
Here are some examples:
http://www.merlinia.com/mdt/WiXTutorial3.msl
http://wix.tramontana.co.hu/tutorial/user-interface/new-link-in-the-chain

Wix custom action is failed to load the dll file?

I am trying to do a custom action at the time of msi installation. But the dll required for my custom action is depends on other dlls. At the time of installtion it is giving the error like "a dll required for this install to complete could not run".How can I load the dependent dll files for this custom action to run properly.
The code that I am using is
<CustomAction Id='CheckingPID' BinaryKey='CheckPID' DllEntry='ValidateKey' />
<Binary Id ='CheckPID' SourceFile='$(sys.CURRENTDIR)\LicenseKeyClient_32d.dll'/>
<Binary Id ='CheckPID2' SourceFile='$(sys.CURRENTDIR)\curllib.dll'/>
<Binary Id ='CheckPID3' SourceFile='$(sys.CURRENTDIR)\libsasl.dll'/>
<Binary Id ='CheckPID4' SourceFile='$(sys.CURRENTDIR)\openldap.dll'/>
The files that you add in binary table usually get extracted with temporary names during the installation, so your DLL will not be able to locate the other DLLs you add next to it.
A workaround is to add those DLLs as normal files in the Temp system folder and delete them when the installation ends. This has the limitation that you need to set your custom action as deferred, so it executes after the files are installed, thus your DLLs get copied to Temp folder.
I don't know if wix has a support for temporary files, similar with the one present in Advanced Installer, but if not you could try to write a custom action to simulate it. Basically what Advanced Installer does is to extract those files in the Temp folder the moment the MSI is launched, and also deletes them when the installation is complete. This has the advantage that you can use the temporary files and in immediate custom actions, i.e. well before the files from your package are installed.
Despite Bogdan's excellent answer, allow me to add my 2 cents:
It looks like you are dealing with some form of license key validation? The best way is generally to deal with your license keys in the application itself, unless you want it written to HKLM instead of HKCU - in which case you might need the temporary admin rights generally acquired during installation.
You can also open a HKLM key for writing during setup, and write it from the application though this is generally frowned upon security-wise. This allows you to write a single license key for all users directly from the application.
The application features more flexibility and control of the process of registering your license key, and crucially an easy way to run the process again. From my perspective this is almost always needed for a serious application - often due to trial versions with the eventual need to register the license key at the end of the trial period from within the application itself - instead of uninstalling the application and reinstalling, or running the setup in repair / maintenance mode - which seems extremely clunky.
I have described this issue previously in some more detail: Reasons to deal with licensing in the application rather than the setup.
I'll also add that WiX DTF .NET custom actions really simplify this problem by allowing you to embed content into the self extracting custom action package and make them available in the current directory at runtime. Very easy.
But yes, Glytzhkof is correct. Any licensing / DRM done inside of an MSI is easily defeated. It's best to do this in the app or both. For example I've worked at companies where it's a share responsibility. You can enter one now or later. I've also worked at companies where the license key had bits embedded in it that drove feature selection. It gets complicated fast so try not to have to go down that road.

Leveraging heat.exe and harvest already localized file names and including them to msi using wix

I have a question whether what i am trying to do is doable, and if the answer is yes how to do it.
I am new to the wix and have been doing some reading on how dynamically to include a folder to an installer and eventually i were able to do a task in nant that uses heat.exe to generate wxs file and latter adding newly generated wxs file to light and candle tasks. This allowed me to add the content of a folder to the msi and subsequently have that folder and its content to be installed.
My problem starts at the point where the folder that i am adding to the msi contains files that has their names already localized (this is a requirement).
When i am adding a file to the directory structure that has its name in Russian for example which is not 1252 codepage i am getting the error:
[exec] ......Templates.wxs(65) : error LGHT0311 : A string was
provided with characters that are not available in the specified
database code page '1252'. Either change these characters to ones that
exist in the database's code page, or update the database's code page
by modifying one of the following attributes: Product/#Codepage,
Module/#Codepage, Patch/#Codepage, PatchCreation/#Codepage, or
WixLocalization/#Codepage.
I tried to set Product/#Codepage to 65001 (UTF-8) however that did not solve the problem.
Eventually what i want to do is to have an ability to add a folder and its content to installer and someone else latter add any number of files that has their names localized into that folder. This way whenever the build runs and subsequent creation of msi happens, msi would contain that folder and its content.
Thank you very much in advance.
This is what WiX.chm says about setting the code page of the MSI database:
You can set this to a valid Windows code page by integer like 1252, or
by web name like Windows-1252. UTF-7 and UTF-8 are not officially
supported because of user interface issues. Unicode is not supported.
As long as you are going to have files named in different languages, that is, File table won't fit into a single Windows code page, you have very little choice. UTF-8 is said to be not officially supported, and this leaves a place for a hope.
If you set the CodePage attribute of the Product element to UTF-8, it will build successfully. And you can install/uninstall the resulting MSI with no problem. I have played a bit with it, and didn't face with any "interface issues" mentioned in that warning above.
Furthermore, I've googled the topic a bit, and found out that InstallShield allows setting the MSI database code page to UTF-8, which is reflected in their docs (search for 'utf-8' on that page). They have more to say about the potential interface issues:
However, some scenarios result in user interface issues. For example,
if an end user specifies the /qb command-line option or uninstalls the
product from Add or Remove Programs, Windows Installer uses very small
fonts to display the user interface text in a UTF-8 database.
They also want to stay on the safe side, hence this setting is false by default (no UTF-8, just ASCII).
So, finally, what would I do in your situation?
if that's a strict requirement to the installation package, use UTF-8 as code page
test all possible scenarios (install / uninstall / repair / upgrade / etc.) on all possible combinations related to localization (English OS, non-English OS, various combinations of current culture and culture UI)
if you face with those ghost "interface issues", show those to your stakeholders, decide whether this is what you can live with and publish known issues if you do
otherwise, recycle this idea and just thank your life for an opportunity to level-up your skills in this area :)
Hope this helps.

Class table generated InprocServer32 value problem

I'm installing an Active X control that contains some COM servers. I'm using InstallShield's COM Extract at Build option to generate the registry information. This results in a lot of entries in the Registry and Class tables. (The extracted information is pretty much the same using Wix).
It appears that my COM Sever is correctly being installed except for an additional value called "InprocServer32" in the InprocServer32 key that looks like this:
HKCR\CLSID\{MY-COM-GUID}\InprocServer32
(Default) = C:\Path-to-my\file.ocx
InprocServer32 = 8tYCAGak)9S9&~swl.$?MyFeatureName>*&N$B'fk?As1x2J653?'
The only think I can make out from the extra value is the MyFeatureName which is the internal name of the MSI feature that contains the .ocx file. The key is not listed in the Registry table so it must be generated by the Class table.
The problem I'm having only happens in Windows Server 2008. It seems that the app trying to use the COM server is failing to find the path to the .ocx file from the (Default) value and instead it is finding the InprocServer32 value. This results in the app launching the MSI and then having the MSI being stuck in what seems like an infinte loop.
I'm wondering if this is a known issue in Windows Server 2008 or whether there is a way to prevent that extra value from being generated by msiexec.
I'd read this article and see if it helps you get where you want to be:
RobMen's Recommendation: Do not advertise COM information in MSI
You might want to turn off InstallShield's COM Extract at Build and instead do a One-Time COM Extract on the component in question. Then you can go into the Component Advanced section and manually manipulate the registry / com table information to be how you want it to be.
If you use WiX at all, another workflow / trick is to use Heat to build an MSI or MSM around your COM server. Then use InstallShield to edit the MSI/MSM in direct mode and the Registry view to export the Registry Keys/Values to a .REG file. Then import that .REG file into your Component in your real install project.
I can't help you diagnose what's going on, I'll just mumble a bit about what this all means. This is a counter-measure against DLL Hell. It is supposed to protect your application against some kind of other install program that could overwrite your COM server registry keys. Specifically the (Default) key which gives the location to your server DLL.
From the fake InprocServer32 value, the app can auto-detect that the Default key was overwritten and automatically launch MSI again to repair the damage. Which is what you see happening.
I thoroughly dislike the feature, it is just one more fail point in something that is already hard to troubleshoot when it blows up. And it is a useless feature, it assumes that the other installer doesn't use the exact same counter-measure. Which would have worked 10 years ago.
No idea what you'd do to troubleshoot this particular failure. Other then just punt this cr*p and let the servers just SelfReg themselves. At least you'll have something to work with when that doesn't work.