Wix bundle "The data area passed to a system call is too small" error - wix

I'm maintaining a bundle created with Wix 3.6. It contains custom BA made with C++ and MFC. Now one Msi inside the bundle got one more digit to its build number. After that installing of bundle fails immediately after started and gives following error (shown on the bundle UI):
0x8007007A, The data area passed to a system call is too small. ERROR_INSUFFICIENT_BUFFER
What system call this could be? Is the buffer something on my code that I can fix?
I tested that error occurs if increasing length of Name or Version attribute of Product element of the Msi. But increasing length of Manufacturer does not generate error. Also, running the Msi separately does not generate any errors.
Combined length of name and version is 47 characters. On bundle title there are 10 additional characters.

Related

How can the contents of an installed file marked Permanent="No" be preserved during an upgrade?

Installers of previous versions of our software include a Component File that was NOT marked with Permanent="Yes". Now, we wish to read the pre-upgrade contents of this file during the upgrade process, which will overwrite the file with different contents. Is there a good way to do this?
It would help if you said exactly what you were doing that would cause the file to be overwritten. Some major upgrades (is that what you're doing?) will do a complete uninstall of the product first, followed by a complete install of the newer product. If that's the situation then use a custom action sequenced before RemoveExistingProducts to back up the file somewhere so that your application can retrieve the content, or get the content you need before it's ovewritten.
If you are doing a major upgrade sequenced later (such as afterInstallExecute) or you are doing a patch then it is by no means certain that the file will be overwritten because file overwrite rules will not replace a file that has been updated since it was installed. If the application altered the file then this type of upgrade will not overwrite it:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370531(v=vs.85).aspx
Or in the case that the file is unchanged since it was installed, change the dates so it appears to be modified, as described here:
https://blogs.msdn.microsoft.com/astebner/2013/05/23/updating-the-last-modified-time-to-prevent-windows-installer-from-updating-an-unversioned-file/
It's also not clear that Permanent=yes is what you want anyway - that would glue the file to the system forever. You may be thinking of NeverOverwrite, but it's typically not required if the app changes the files, and easier to decide at upgrade time (by changing dates) instead of committing to NeverOverwrite when it's sometimes unclear what the product may need in the future.
A comment refers to retrieving the previous version of the product during the upgrade. There are a number of ways to do this:
If you know the ProductCode of the previous version, MsiGetProductInfo (and equivalents in script etc) will return product version values or strings:
https://msdn.microsoft.com/en-us/library/aa370130(v=vs.85).aspx
Or if you'd rather not hardcode the value, MsiEnumProducts passing the UpgradeCode will return a list of installed ProductCodes. This technique is most useful if you have your own bootstrapper or UI where you want to show the user the current installed version.
In a WiX major upgrade the associated property (WIX_UPGRADE_DETECTED) is a list of the ProductCodes detected (usually a list of one) so you can use that to get the version of the product being upgraded. In a small vbscript example, something like:
set installer = CreateObject("WindowsInstaller.Installer")
and:
prodversionstring = installer.productinfo(WIX_UPGRADE_DETECTED, "VersionString")
will get you close.
Assuming this file is a configuration file such as an XML file, I find this is just a tough area of Windows Installer. You ship file version 1, the end user modifies certain attributes and then you ship file version 2 to which you want to preserve those customizations.
The problem is this is a very complex merge. It works somewhat OK if you only care about 1-2 attributes but if the answer is I need to preserve all of it then you are stuck between losing all the customizations or not getting the changes from version 2 of the file.
You could write extensive custom actions to do all this during the installer but I propose there is a better way: Have 2 files.
1 file that is owned by the installer and can always be safely overwritten and 1 file that is owned by the application that overrides are stored in. Think of it like a transformation file. The installer doesn't know about this file so it never overwrites or deletes it. (The very definition of user data from an MSI perspective.)
For example the .NET framework Web.Config schema AppSettings element has a file attribute that was designed to support this nicely.
Specifies a relative path to an external file containing custom
application configuration settings. The specified file contains the
same kind of settings that are specified in the , , and
elements and uses the same key/value pair format as those
elements. The path specified is relative to the main configuration
file. For a Windows Forms application, this would be the binary folder
(such as /bin/debug), not the location of the application
configuration file. For Web Forms applications, the path is relative
to the application root, where the web.config file is located.
Note that the runtime ignores the attribute if the specified file can
not be found.

Overwrite MSI DisplayVersion with Custom String

I have a .msi installer (via wix) for an application I'm working on but the application's version number doesn't fit the X.Y.Z version numbers required my MSI's registry Version so the version number is "mangled" into something that does fit and still increases with every release.
I'm okay with this.
msiexec, as part of it's final cleanup, converts this X.Y.Z integer-encoded version number into a string and dumps it into the DisplayVersion registry entry. What I'd like to do is overwrite that string with my own that contains the actual version number of my application.
This certainly seems possible. For example...
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\19BF4688EE4961F41A44D0282A2340D9\InstallProperties
DisplayName = (REG_SZ) "Configuration Manager Client"
LocalPackage = (REG_SZ) "C:\Windows\Installer\41202.msi"
DisplayVersion = (REG_SZ) "5.00.7958.1000"
Version = (REG_DWORD) 0x05001f16
The Version is the encoded value of "5.00.7958", so where did the rest of the DisplayVersion string come from?
How, using only wix/msi supported options, do I overwrite DisplayVersion in the registry with my own custom string?
Might be a larger change than what you're looking to make, but...
if you set ARPSYSTEMCOMPONENT=1 in your MSI it won't register an ARP entry for your product. Then you can create your own ARP entry for your product by populating the HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductCode] keys in the Registry table of your MSI.
I eventually accomplished this by having the MSI launch a custom installer binary near the end of the installation procedure. That program forks a background copy of itself and exits so that the install can finish.
The background task sleeps for a while to let the installation complete and then directly alters the registry to set DisplayVersion to the desired string.
There's a race condition here but it hasn't been a problem and updating the string isn't essential.

wix installer ice03 Invalid Language Id

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

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.

Max number of times a DLL can be registered/unregistered?

Is there a maximum number of times that a DLL can be registered and unregistered in a specific time period?
Here's what I mean and why: I have a Continuous Integration package that builds my VB6 applications and in order to build each of the 80 components of the solution, I:
retrieve each project's dependencies
in turn
register the dll (in NAnt
using < comregister unRegister="false" ... ... >)
build the project
publish the output .dll or .exe
somewhere safe
un-register the dll (in NAnt using
< comregister unRegister="true" ...
... >)
Now, this all works 100% of the time, IF I build each of the 80 projects manually; however, if I get my NAnt script to build all 80 projects in turn (in the correct order) then the build fails, giving me this error in CruiseControls' output...
[comregister] Unregistering 1 files
[comregister] c:\location\myBuild.include(301,4): Error while unregistering 'c:\\[project-location]\lib\myDependentDLLFile.dll' Unable to find an entry point named '**DllUnregisterServer**' in DLL 'c:\\[project-location]\lib\myDependentDLLFile.dll'.
(I don't know where 'DllUnregisterServer' comes from though!)
The same error then appears for every subsequent project that I build past the point of failure, which is around the 50-projects-built area. What I mean, is that the first 50 projects build fine, then the rest fail in-turn.
I have mitigated this by using the failonerror="false" attribute within the comregister call inside NAnt, but this then throws doubt in my mind as to whether this is ok or not...!
Ideally, I'd like to remove the failonerror attribute and report genuine errors back to CruiseControl's logging facilities. Any thoughts or suggestions?
No there's no maximum. Use Dumpbin.exe or Depends.exe to take a look inside that DLL and check that DllUnRegisterServer entry point is actually defined.
I dont think teher is any limit to the no of DLL register/unregister.