Skip to content

HUGE OPTIMIZATIONS!

Choose a tag to compare

@MapleSyrupLover MapleSyrupLover released this 08 Aug 00:06
· 2 commits to master since this release

BuzzInstaller 1.1.0 — Release Notes

Executive Summary

This release delivers two major improvements: a 81% reduction in executable size for both BuzzInstaller.exe and BuzzInstallerInstaller.exe, and critical stability fixes for the PyInstaller onefile cleanup, background process lifecycle, and Windows shortcut integration.


1. Executable Size Comparison

BuzzInstaller.exe

Metric Before After Change
Size (bytes) 256,744,993 49,408,266 -207,336,727
Size (MiB) ~245 MiB ~47 MiB -81%

BuzzInstallerInstaller.exe

Metric Before After Change
Size (bytes) ~250,000,000 46,773,568 -203,226,432
Size (MiB) ~240 MiB ~45 MiB -81%

Combined savings: ~410 MB across both executables

Why was it so large?

Both build scripts used --collect-all PySide6, which instructs PyInstaller to bundle every PySide6 module and plugin — including dozens of optional Qt modules that neither application uses:

  • QtWebEngine (~70 MB) — full Chromium browser engine
  • Qt3D (~30 MB) — 3D rendering framework
  • QtQuick/QtQml/QtDeclarative (~20 MB) — QML engine
  • QtCharts + QtDataVisualization (~15 MB) — data visualization
  • QtPdf (~10 MB) — PDF rendering
  • QtBluetooth/QtNfc/QtSerialPort/QtSensors (~15 MB) — hardware interfaces
  • QtQuick3D/QtSpatialAudio/QtMultimedia/QtWebSockets (~25 MB) — multimedia/3D/audio
  • Plus ~30 more optional modules

Neither BuzzInstaller nor BuzzInstallerInstaller uses any of these — both are pure QtWidgets applications (buttons, labels, progress bars, file dialogs).

What changed

src/BuzzInstaller/build/build_exe.py and src/BuzzInstallerInstaller/build/build_installer.py:

  • Removed --collect-all PySide6 — the primary fix
  • PyInstaller's standard hook-PySide6.py now collects only the actually imported modules (QtWidgets, QtCore, QtGui, QtNetwork) plus the required Qt plugins (platforms, imageformats, styles)
  • Removed unnecessary hidden imports (PySide6.QtXml, PySide6.QtMultimedia) from BuzzInstaller
  • Added system.background_launcher to hidden imports (new module from the handoff fix)
  • No functionality was removed — no modules were excluded because they were large; they were simply no longer force-collected when not imported

2. Fixes in this Release

Fix 1: PyInstaller "_MEI" Temporary Directory Cleanup Warning

Problem: When BuzzInstaller.exe (PyInstaller onefile) spawned --background, the child's bootloader inherited the parent's _MEIPASS2 environment variable and reused the parent's _MEI* extraction directory. The background process is intentionally long-lived, so it kept Qt DLLs loaded from the parent's directory — locking it. When the foreground exited, PyInstaller failed with:

Failed to remove temporary directory:
C:\Users\elial\AppData\Local\Temp\_MEIxxxxxx

Solution — background handoff mechanism:

src/BuzzInstaller/system/background_launcher.py (NEW):

  • A short-lived intermediary that waits for the foreground process to fully exit (via WaitForSingleObject — no fixed delays, no busy-wait)
  • Imports ONLY the standard library — holds no files from the parent's _MEI* directory
  • Strips _MEIPASS2 from the environment when launching the final --background process

src/BuzzInstaller/system/background_service.py (MODIFIED):

  • In frozen mode, --background is never spawned directly from the foreground
  • Instead, _launch_background_via_launcher() uses PowerShell as the intermediary (since sys.executable is the bundled exe, not python): waits via Wait-Process for the foreground PID, sets $env:_MEIPASS2 = $null, then launches BuzzInstaller.exe --background with -WindowStyle Hidden
  • Non-background launches (download UI) still spawn directly with _MEIPASS2 stripped
  • Source mode still spawns directly (no launcher needed)

Fix 2: Clean Shutdown Behavior

src/BuzzInstaller/core/buzzheavier_api.py (MODIFIED):

  • Added BuzzHeavierAPI.close() to release the requests.Session (connection pools/sockets) before process exit
  • Fixed get_download_url() to close HTTP responses with resp.close() in a finally block

src/BuzzInstaller/main.py (MODIFIED):

  • run_upload(): Added service.api.close() in worker's finally block; thread join after app.exec()
  • run_download(): Added worker_done Event, service.api.close() in finally block; thread join after app.exec()
  • Background mode: shutdown logging around svc.run() and svc.stop()
  • __main__: exit logging

Fix 3: Windows Shortcut Creation

src/BuzzInstallerInstaller/shortcut.py (NEW):

  • create_shortcut(), delete_shortcut(), get_shortcut_target() using PowerShell's WScript.Shell COM — creates real .lnk files, not text

src/BuzzInstallerInstaller/installer.py (MODIFIED):

  • create_shortcut_for_installed() creates C:\BuzzInstaller\BuzzInstaller.lnk after install/update — non-fatal on permission failure
  • delete_buzzinstaller() removes the shortcut, and only removes C:\BuzzInstaller if empty (unrelated files preserved)

3. Verification Results

Check Result
Version tests ✅ 10/10 PASS
Installer tests ✅ 24/24 PASS
Improvements tests ✅ 19/19 PASS
Shortcut tests ✅ 13/13 PASS
Background handoff tests ✅ 8/8 PASS
Total tests 74/74 PASS
BuzzInstaller.exe --version ✅ "BuzzInstaller 1.1.0"
BuzzInstaller.exe --background ✅ Idle event loop running
BuzzInstallerInstaller.exe UI ✅ Launched, real Qt GUI (69 MB working set)
Build compile checks ✅ All modified files compile

NOTE: ADD bz.cmd TO "C:\WINDOWS\System32\bz.cmd" FOR THE BZ CLI