Add executable versioning support for Windows builds
- Implemented `set_exe_version` method in `WindowsBuilder` to set the version information for the generated executable. - This ensures proper MSI updates by comparing file versions. - Added error handling for missing `pefile` dependency and version resource. - Updated `requirements-dev.txt` to include `pefile` as a dependency for building.
This commit is contained in:
parent
a8aa54fa5e
commit
bf7c7b5e5f
5 changed files with 2932 additions and 2874 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -145,6 +145,9 @@ class WindowsBuilder:
|
|||
if total_size > 0:
|
||||
print(f" Total size: {total_size / 1024 / 1024:.1f} MB")
|
||||
|
||||
# Set executable version information (required for MSI updates)
|
||||
self.set_exe_version(exe_path)
|
||||
|
||||
# Generate SHA256 checksum
|
||||
self.generate_checksum(exe_path)
|
||||
|
||||
|
|
@ -169,6 +172,52 @@ class WindowsBuilder:
|
|||
print(f" File: {checksum_file}")
|
||||
print(f" Hash: {checksum}")
|
||||
|
||||
def set_exe_version(self, exe_path: Path) -> None:
|
||||
"""Set executable file version for Windows.
|
||||
|
||||
This is important for MSI updates: Windows Installer compares file versions
|
||||
to determine if files should be updated during a major upgrade.
|
||||
|
||||
Args:
|
||||
exe_path: Path to the executable file
|
||||
"""
|
||||
print("\n🏷️ Setting executable version information...")
|
||||
|
||||
try:
|
||||
import pefile
|
||||
except ImportError:
|
||||
print("⚠️ pefile not installed - skipping EXE version update")
|
||||
print(" Note: Install with: pip install pefile")
|
||||
print(" EXE version info will be blank (MSI updates may not work correctly)")
|
||||
return
|
||||
|
||||
try:
|
||||
pe = pefile.PE(str(exe_path))
|
||||
|
||||
# Parse version into 4-part format (Major, Minor, Build, Revision)
|
||||
version_parts = self.version.split(".")
|
||||
while len(version_parts) < 4:
|
||||
version_parts.append("0")
|
||||
|
||||
file_version = tuple(int(v) for v in version_parts[:4])
|
||||
|
||||
# Set version resource if it exists
|
||||
if hasattr(pe, "VS_FIXEDFILEINFO"):
|
||||
pe.VS_FIXEDFILEINFO[0].FileVersionMS = (file_version[0] << 16) | file_version[1]
|
||||
pe.VS_FIXEDFILEINFO[0].FileVersionLS = (file_version[2] << 16) | file_version[3]
|
||||
pe.VS_FIXEDFILEINFO[0].ProductVersionMS = (file_version[0] << 16) | file_version[1]
|
||||
pe.VS_FIXEDFILEINFO[0].ProductVersionLS = (file_version[2] << 16) | file_version[3]
|
||||
|
||||
# Write modified PE back to file
|
||||
pe.write(filename=str(exe_path))
|
||||
print(f"✅ Version set to {self.version}")
|
||||
else:
|
||||
print("⚠️ No version resource found in EXE")
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not set EXE version: {e}")
|
||||
print(" MSI updates may not work correctly without file version info")
|
||||
|
||||
def create_msi(self) -> bool:
|
||||
"""Create MSI installer using WiX Toolset.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue