-
-
Notifications
You must be signed in to change notification settings - Fork 60
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.
- Project facts
- Embedded resources (the payload)
- Install flow
- Integrity verification (Hashes.json)
- Uninstall registry keys written
- Silent mode
- Localization
- See also
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.
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"]
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.
The flow runs in Main.xaml.cs → Window_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:
-
WindowCorner/LoadBackground(UI only; skipped when silent). The background is a randomAssets/Background{1..36}.jpg. -
TerminateProcess("Sucrose")twice with delays — kills any running Sucrose processes (except the installer itself). -
RefreshDesktop(Skylark.WingDesktop.RefreshDesktop). - Clean staging:
ControlDirectory(Packages/SevenZip/Showcase), thenControlDirectoryStable(InstallPath)(deletes existing install files/folders but keeps the root). -
ExtractResources— extract the embeddedPackages,SevenZip, andShowcaseresources to their temp/AppData targets. -
ExtractAll— extract the app.7zintoInstallPath:-
Primary:
ExtractArchiveruns%TEMP%\SevenZip\7z.exe x "<Packages>\Sucrose.7z" -o"<InstallPath>" -aoa(overwrite all). -
Fallback 1:
ExtractPackagesvia SharpCompressArchiveFactory. -
Fallback 2:
ExtractArchive(resource, InstallPath)reads the embeddedPackages\Sucrose.7zresource stream via SharpCompress.
-
Primary:
-
HashesResources(Checksum, InstallPath)— integrity check (see below). -
If hashes pass:
-
CreateShortcuts— Desktop + Start Menu Programs.lnknamedSucrose Wallpaper Engine.lnkpointing to the Launcher (Skylark.WingShortcutBasic.Create, fallbackShortcutDefault.Create). -
SetUninstall— writes theHKCU\...\Uninstall\Sucroseregistry values. -
Process.Start(Launcher)— launches Sucrose.
-
-
If hashes fail: re-clean the install dir; if
Template.htmlexists,Process.Start(Template.html)shows the localized "Installation Error / ERROR_CHECKSUM_MISMATCH" page, which offers re-download from GitHub / Microsoft Store / SourceForge / Official Website. -
Close().
- The per-architecture
Checksum\<Platform>\Hashes.jsonis embedded. It is a JSONDictionary<string,string>ofrelativeFilePath → MD5 hash. - After extraction, every entry's file is hashed via
Skylark.Standard...HashExtension.FileToMD5Async(throttled by aSemaphoreSlim,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 theX64/X86/ARM64preprocessor symbol.
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.
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
MessageBoxtitled "Bundle Error Information - v".
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.
Getting Started
- Installation
- System Requirements
- Quick Start
- Portal Interface Tour
- Updating Sucrose
- Uninstalling Sucrose
Wallpaper Types
Using Sucrose
- Managing Library
- Using Store
- Customizing Wallpaper
- Multi-Monitor
- Wallpaper Cycling
- Choosing Engines
- Performance Rules
- Theme, Tray & Startup
- Discord Rich Presence
Settings Reference
- Settings Overview
- Settings: General
- Settings: Personal
- Settings: Performance
- Settings: Wallpaper
- Settings: System
- Settings: Other
- Settings: All Keys
Creating Wallpapers
- Create Overview
- Create: Step By Step
- Create: Package Format
- Create: Customization Controls
- Create: JS Bridge
- Create: Audio API
- Create: System API
- Create: Property Listener & Filters
- Create: Web Architecture
- Create: Compatibility
- Create: Example Wallpapers
- Create: Sharing & Publishing
Engine Reference
- Engines Overview
- Engine: MpvPlayer
- Engine: VlcPlayer
- Engine: WebView
- Engine: CefSharp
- Engine: Nebula
- Engine: Vexana
- Engine: Xavier
- Engine: Aurora
- Engine Comparison
Automation & Command Line
Architecture & Internals
- Architecture Overview
- Lifecycle
- Commandog Dispatcher
- Single-Instance Mutexes
- IPC
- Backgroundog Service
- Crash Reporting
- Update Internals
- Property Service
- Undo Internals
Data, Files & Diagnostics
Building & Contributing
- Building From Source
- Repository Layout
- Shared Item Projects
- Code Conventions
- Preprocessor Symbols
- Publish Pipeline
- Bundle Installer Internals
- Extending Sucrose
- Contributing
- Translating with Localizer
- Localization Coverage
- Security Policy
- Privacy & Telemetry
Help & Support