Skip to content

Bundle Installer Internals

Taiizor edited this page Jun 5, 2026 · 3 revisions

Bundle Installer Internals

Sucrose.Bundle is the file users actually download and run. It is a single self-extracting WPF .NET Framework 4.8 executable, one per architecture, that carries the entire compressed app payload plus the 7-Zip binaries, an MD5 checksum manifest, and the starter Showcase wallpapers as embedded resources. This page explains the project setup, the embedded resources, the exact install flow, the integrity verification, the registry keys it writes, and how silent mode works. For how the embedded .7z is produced, see Publish Pipeline; for the end-user view of installing, see Installation.

Contents

Project facts

Location: src/Bundle/Sucrose.Bundle/. Solution: src/Sucrose.Bundle.slnx.

Property Value
SDK Microsoft.NET.Sdk, UseWPF=true, OutputType=WinExe
Target framework net48 (.NET Framework 4.8)
Assembly name / startup AssemblyName=Sucrose.Bundle, StartupObject=Sucrose.Bundle.App
Output path $(BaseOutputPath)\Bundle\{x86|x64|ARM64} (i.e. src/Sucrose/Bundle/<arch>)
Single-file ExcludeFromSingleFile=true
Key packages Skylark, Skylark.Wing, SharpCompress, Skylark.Standard, and Costura.Fody (IL-merges all dependencies into one .exe, configured via FodyWeavers.xml<Costura />)
App manifest requestedExecutionLevel level="asInvoker" (no admin), dpiAware true/PM, dpiAwareness PerMonitorV2, PerMonitor

Because the installer targets .NET Framework 4.8, the Chocolatey package declares a hard dependency dotnetfx >= 4.8.0.20220524 (the other package managers do not). The 4.8 download link is https://dotnet.microsoft.com/en-us/download/dotnet-framework/net48.

Embedded resources (the payload)

flowchart LR
    subgraph Exe["Sucrose.Bundle.exe (net48, Costura single-file)"]
      R1["Packages / Sucrose.7z"]
      R2["SevenZip / 7z.exe"]
      R3["Checksum / Hashes.json"]
      R4["Checksum / Template.html"]
      R5["Showcase / **"]
    end
    R1 --> Install["%LocalAppData%/Sucrose<br/>app installed here"]
    R2 --> Temp["%TEMP%/SevenZip<br/>extractor"]
    R5 --> Show["%AppData%/Sucrose/Showcase<br/>starter wallpapers"]
    Install --> Check{"Hashes.json MD5 verify"}
    Check -->|pass| Done["create shortcuts +<br/>HKCU Uninstall key +<br/>launch Launcher"]
    Check -->|fail| Err["show Template.html<br/>checksum error page"]
Loading

Defined as <EmbeddedResource> items in Sucrose.Bundle.csproj (the logical names matter — Main.xaml.cs reads them by prefix):

Source Logical name Purpose
Showcase\** Showcase\... Default starter wallpapers shipped with the install
Checksum\*.html Checksum\... The Template.html error page
Checksum\$(Platform)\** Checksum\... Per-arch Hashes.json — the MD5 manifest of expected installed files
SevenZip\7z-$(Platform)\** SevenZip\... The 7z.exe + dlls used to extract the payload
$(BaseOutputPath)\Package\Compressed\net10.0-windows\Sucrose-$(Platform).7z Packages\Sucrose.7z The actual app, produced by .build/Sucrose.ps1

The 7-Zip binaries live at src/Bundle/Sucrose.Bundle/SevenZip/7z-{x64,x86,ARM64}/. Building the Bundle requires that .build/Sucrose.ps1 has already produced Sucrose-<arch>.7z — building the Bundle first will fail to find that embedded resource.

Install flow

The flow runs in Main.xaml.csWindow_ContentRendered. Key paths (all under the user profile — no admin):

Path Meaning
%LocalAppData%\Sucrose Install path (InstallPath)
%LocalAppData%\Sucrose\Sucrose.Launcher\Sucrose.Launcher.exe Launcher exe
%LocalAppData%\Sucrose\Sucrose.Undo\Sucrose.Undo.exe Uninstaller
%AppData%\Sucrose\Showcase Showcase target
%TEMP%\Packages, %TEMP%\SevenZip, %TEMP%\Template.html Temp staging

Steps performed in order:

  1. WindowCorner / LoadBackground (UI only; skipped when silent). The background is a random Assets/Background{1..36}.jpg.
  2. TerminateProcess("Sucrose") twice with delays — kills any running Sucrose processes (except the installer itself).
  3. RefreshDesktop (Skylark.Wing Desktop.RefreshDesktop).
  4. Clean staging: ControlDirectory(Packages/SevenZip/Showcase), then ControlDirectoryStable(InstallPath) (deletes existing install files/folders but keeps the root).
  5. ExtractResources — extract the embedded Packages, SevenZip, and Showcase resources to their temp/AppData targets.
  6. ExtractAll — extract the app .7z into InstallPath:
    • Primary: ExtractArchive runs %TEMP%\SevenZip\7z.exe x "<Packages>\Sucrose.7z" -o"<InstallPath>" -aoa (overwrite all).
    • Fallback 1: ExtractPackages via SharpCompress ArchiveFactory.
    • Fallback 2: ExtractArchive(resource, InstallPath) reads the embedded Packages\Sucrose.7z resource stream via SharpCompress.
  7. HashesResources(Checksum, InstallPath) — integrity check (see below).
  8. If hashes pass:
    • CreateShortcuts — Desktop + Start Menu Programs .lnk named Sucrose Wallpaper Engine.lnk pointing to the Launcher (Skylark.Wing ShortcutBasic.Create, fallback ShortcutDefault.Create).
    • SetUninstall — writes the HKCU\...\Uninstall\Sucrose registry values.
    • Process.Start(Launcher) — launches Sucrose.
  9. If hashes fail: re-clean the install dir; if Template.html exists, Process.Start(Template.html) shows the localized "Installation Error / ERROR_CHECKSUM_MISMATCH" page, which offers re-download from GitHub / Microsoft Store / SourceForge / Official Website.
  10. Close().

Integrity verification (Hashes.json)

  • The per-architecture Checksum\<Platform>\Hashes.json is embedded. It is a JSON Dictionary<string,string> of relativeFilePath → MD5 hash.
  • After extraction, every entry's file is hashed via Skylark.Standard...HashExtension.FileToMD5Async (throttled by a SemaphoreSlim, ThrottlerCount = 85) and compared case-insensitively.
  • A missing file or a mismatch → overall failure → the error page (step 9).
  • The embedded HTML/JSON templates {Version} and {Architecture} placeholders at run time; {Architecture} is resolved by the X64/X86/ARM64 preprocessor symbol.

Uninstall registry keys written

SetUninstall writes these under HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Sucrose:

Value Content
DisplayName "Sucrose Wallpaper Engine"
Publisher / PublisherName "Taiizor"
DisplayVersion / BundleVersion the version
DisplayIcon Launcher path
InstallLocation %LocalAppData%\Sucrose
UninstallString ...\Sucrose.Undo\Sucrose.Undo.exe
QuietUninstallString "<Uninstall>" -s
EstimatedSize DWord, KB
NoModify / NoRepair 1 / 1
Contact taiizor@vegalya.com
URLInfoAbout / URLUpdateInfo https://github.com/Taiizor/Sucrose
Comments description

The install is per-user (HKCU, %LocalAppData%), so the uninstall entries are HKCU too. The actual uninstall logic lives in the separate Sucrose.Undo project — see Undo Internals and Uninstalling Sucrose. As of v26.6.4.0, uninstall also restores previously hidden desktop icons.

Silent mode

Defined in App.xaml.cs:

  • Accepts -s, /s, -silent, /silent.
  • In silent mode the window is Collapsed, Opacity=0, Hide(), ShowInTaskbar=false.
  • All package managers (Chocolatey, Scoop, WinGet) invoke the installer with /s, so they are thin wrappers that silently run the GitHub Release .exe.
  • Global exception handlers show a MessageBox titled "Bundle Error Information - v".

Localization

At startup the Bundle loads Properties/Resources_<LANG>.xaml based on CurrentUITwoLetterISOLanguageName, defaulting to EN. About 48 Resources_<LANG>.xaml files exist, and the checksum error page (Template.html) carries 29 inline UI translations. See Localization Coverage for the app-wide language story.

See also

Home

Getting Started

Wallpaper Types

Using Sucrose

Settings Reference

Creating Wallpapers

Engine Reference

Automation & Command Line

Architecture & Internals

Data, Files & Diagnostics

Building & Contributing

Help & Support

Clone this wiki locally