Build environment: Ubuntu LTS (16.04 through 22.04)
Builds of recent versions of KeePass (since at least v2.53) are somehow generating a different assembly version for the main KeePass.exe binary, even when the build environment remains identical. This has been repeatedly observed by me, even with consecutive builds done immediately after each other.
This distinct assembly version results in the "Invalid data format" on launch of KeePass that has been reported previously in a discussion thread for KeePass. That report is found here:
https://sourceforge.net/p/keepass/discussion/329221/thread/6331362061/
So I am confirming that this issue does indeed exist in recent KeePass versions. Somehow it seems that the assembly version written to the KeePass.exe binary is being generated in a non-deterministic fashion. Having had a cursory look at changes with KeePass source code since after v2.52 I'm not sure what change(s) caused this behaviour.
Various public builds of mine for a Launchpad PPA (Ubuntu-based systems) are available where the assembly version of the KeePass.exe binary can be checked, to verify that a distinct version is indeed being created for each build. For most recent KeePass 2.57 please see these links (assembly version that is actually reported for KeePass.exe is quoted next to each Ubuntu version):
Ubuntu 22.04 - 2.57.0.23724
https://launchpad.net/~savoury1/+archive/ubuntu/encryption/+build/28512645
Ubuntu 20.04 - 2.57.0.23722
https://launchpad.net/~savoury1/+archive/ubuntu/encryption/+build/28512644
Ubuntu 18.04 - 2.57.0.23717
https://launchpad.net/~savoury1/+archive/ubuntu/encryption/+build/28512642
Ubuntu 16.04 - 2.57.0.23716
https://launchpad.net/~savoury1/+archive/ubuntu/encryption/+build/28512641
The command used for verifying the assembly version is as follows:
/usr/bin/monodis --assembly /usr/lib/keepass2/KeePass.exe
For these most recent builds linked above the workaround that I have used to prevent the "Invalid data format" pop-up on launch of KeePass is to read the actual assembly version used directly from the built KeePass.exe binary. Given I am building for Ubuntu systems I am doing this in the debian/rules file (which is essentially a GNU makefile) with this code, where $(CURDIR) is the build directory being used:
BINARY = $(CURDIR)/debian/keepass2/usr/lib/keepass2/KeePass.exe
CONFIG = $(BINARY).config
VERSION = /usr/bin/monodis --assembly $(BINARY) | sed -n 's/Version:[ ]\+\([.0-9]\+\)$$/\1/p'
sed -i "s%\(newVersion=\"\)[.0-9]\+%\1`echo $$($(VERSION))`%" $(CONFIG)
This code simply re-writes the KeePass.exe.config file with the actual assembly version, which means that on launch of KeePass there is no "Invalid data format" message displayed. Although this code does fix the problem it would be good to figure out how/why the assembly version written to the main KeePass.exe binary is being generated in a non-deterministic fashion.
Since the first release, "
2.X.Y.*" is specified for theAssemblyVersionattribute (in the 'KeePass/Properties/AssemblyInfo.cs' file), which lets the compiler choose the last part of the assembly version. In the 'KeePass.exe.config' file, the same version must be specified (otherwise the binding redirect doesn't work and thus some plugins aren't loaded properly). Since version 2.52, KeePass checks the 'KeePass.exe.config' file and shows a warning dialog when finding a problem (e.g. different versions).The main reason why an asterisk is specified in the version has to do with PLGX plugins: the plugin folder name in the PLGX cache directory must depend on the current 'KeePass.exe' assembly (otherwise it could happen that a compatibility problem between KeePass and a PLGX plugin is not always detected); this holds for stable releases and development snapshots (for which the first 3 parts of the version are the same as the latest stable release). The easiest solution is to let the compiler generate a new number as the last part of the version and make the plugin folder dependent on it.
However, I have an idea how the asterisk in the version could be removed. When determining the plugin folder name, a stable release could simply use the version (without asterisk), whereas a development snapshot could use the SHA-256 hash of the 'KeePass.exe' file. With this, development snapshots would be slightly slower than stable releases (as the SHA-256 hash needs to be computed), but I think that's acceptable.
I'm planning to implement this for KeePass 2.58 and will post here when it's done. Before that, there will be a 2.57.1 release (i.e. you'll need your solution one more time).
Thanks and best regards,
Dominik
I've now implemented what I described in my previous post. The revision component of the assembly version is now invariant (0 instead of an asterisk) and all affected code (PLGX cache item identifiers, 'KeePass.exe.config' check, etc.) has been adjusted accordingly.
So, for building KeePass 2.58 or higher, you can simply copy the 'KeePass.exe.config' file from the 'Ext' folder to the output folder, i.e. you do not need to adjust the versions in that file anymore.
If you want to check/test it, here's the source code of the current development snapshot, with the version set to 2.57.1:
https://keepass.info/filepool/KeePass_241017_Source.zip
This package is intended for checking/testing only; please don't publish it anywhere (because there are also other changes since the official 2.57.1 release, the 'KeePassLib.dll' file is not signed, etc.).
Thanks and best regards,
Dominik
Thanks Dominik for the fix of this build issue! For Ubuntu LTS users (16.04, 18.04, 20.04, 22.04, and 24.04) wanting latest KeePass 2.58 including this and other fixes it is now available at my encryption PPA here:
https://launchpad.net/~savoury1/+archive/ubuntu/encryption
Okay, thanks! :-)