Detailed contents
The contents opened out to the section level - for going straight to a place.
Searches chapter and section headings - not the full text
Part I - Tutorial
1.1What an installer does1.2What you write, what rubrapack makes1.3Getting rubrapack1.4A terminal, for those who have not used one1.5The folder you work in1.6Words used in this tutorial
2.1The source2.2Building2.3Installing and removing it2.4What happened inside2.5Check it without building2.6The same, with questions instead of a text editor
3.1One source for every version3.2What Windows does with two versions3.3Version numbers3.4Two identifiers3.5Check the upgrade before users do3.6Small fixes as a patch: patch3.7Earlier versions made by another tool3.8Add-ons that go with the product
4.1The folder4.2The source4.3Folders: [dir.ID]4.4One file: [file.ID]4.5Many files: [files.ID]4.6An empty folder: [folder.ID]4.7Cleaning up: [remove.ID]4.8A second copy: [copy.ID]4.9Two more keys you may meet4.10What happened inside
5.1The source5.2Shortcuts: [shortcut.ID]5.3The Installed apps entry: [arp]5.4A name in another script5.5Try it5.6What happened inside
6.1The source6.2Choosing a set of pages: ui6.3The license: license6.4The install folder6.5A picture at the top: banner6.6Your own words: [ui-text.ID]6.7Starting the program at the end: launch6.8Saving the log: save-log6.9Try it6.10What happened inside
7.1The source7.2Adding a language: languages7.3A license per language: license-xx7.4A text per language: text-xx7.5Languages other than English and Korean7.6Typefaces7.7What is not translated7.8Try it7.9What happened inside
8.1Features8.2The source8.3Declaring features: [feature.ID]8.4Putting files in features: feature8.5What the user sees8.6Choosing from the command line8.7Changing the choice later8.8What happened inside
9.1Properties9.2The source9.3Your own property: [property.NAME]9.4Installing something only when: when9.5Refusing to install: [require.ID]9.6Looking around first: [search.ID]9.7Remembering the install folder9.8What happened inside
10.1Three scopes10.2The source10.3A dual package10.4A guarded install folder: guard10.5Try it10.6What happened inside
11.1The registry in two minutes11.2The source11.3Registry values: [registry.ID]11.4Environment variables: [env.ID]11.5INI files: [ini.ID]11.6File types: [assoc.ID]11.7Links: [protocol.ID]11.8Right-click menus: [menu.ID]11.9COM classes: [com.ID]11.10Try it11.11What happened inside
12.1The source12.2A service: [service.ID]12.3A font: [font.ID]12.4Access rights: [permission.ID]12.5Programs that are still running: the preflight12.6Restarting: reboot12.7Try it12.8What happened inside
13.1Why not just run a program?13.2The source13.3[action.ID]13.4What happens when13.5Try it13.6What happened inside
14.1The source14.2A page: [dialog.ID]14.3Where things go on the page14.4Controls: [dialog-control.ID]14.5Every value needs a default: [property.NAME]14.6Try it14.7What happened inside
15.1The folder15.2The source15.3Cabinets and compression15.4Several architectures: --arch15.5The same bytes every time: --reproducible15.6Names from a Mac: --nfc15.7Variables from the command line: -D15.8Somebody else's part: [merge.ID]15.9What happened inside
16.1What a signature is16.2Signing with a key file16.3Timestamps: signatures that outlive the certificate16.4A key in the Windows certificate store16.5A hardware token: PKCS#1116.6Checking a signature: verify16.7External cabinets are not covered16.8What happened inside
17.1MSI or MSIX?17.2The folder17.3The source17.4The package's identity: [msix]17.5The application: [msix-app.ID]Names in several languages, logos in several sizes17.6Extras: [msix-extension.ID]17.7What the package asks for: capabilities and dependencies17.8Optional and modification packages17.9What the other tables become17.10Building for testing: --unsigned-test17.11Signing it17.12All architectures in one file: a bundle17.13Updates from a web site: .appinstaller17.14Compression17.15What happened inside
18.1Checking a source: lint18.2Checking a package: lint <file>18.3Looking at the tables: inspect18.4Files and streams18.5Unpacking without installing: extract18.6A change for one site: transform18.7Signatures: verify18.8MSIX packages18.9Faster test builds: --compress none18.10GUIDs: guid18.11What an error means: explain18.12For scripts: --json18.13Help on the command line
19.1A source from answers: new19.2From an existing package: new --from19.3Changing a source: edit19.4A release script19.5On a build server19.6In an editor: schema19.7With an AI assistant19.8Several packages, one setup program: [chain]19.9Where to go from here
Part II - Reference
20.1Getting startedA first packageA license page and optional partsWhere the rest is explained20.2Example20.3Source format20.4The TOML subset20.5TablesMSIX packagesRegistering with an installed program: [action.ID]Registry values: [registry.ID]Shortcuts: [shortcut.ID]File types and links: [assoc.ID], [protocol.ID]Explorer's right-click menu: [menu.ID]COM classes: [com.ID]Explorer handlers: [handler.ID]MSIX only: [msix-extension.ID]Removing and copying: [remove.ID], [copy.ID]Environment variables: [env.ID]INI files: [ini.ID]Several packages in one setup: [chain]Merge modules: [merge.ID]Writing a merge module: [module]Searching and requiring: [search.ID], [require.ID]Services, fonts and permissionsPer-user and dual packages: scopeCabinetsInstalled apps entry and propertiesInstalling from the command lineInstalling without a windowDialogs: uiSeveral languagesIcon, the finished page, and the scope pageYour own dialog pages: [dialog.ID], [dialog-control.ID]Architectures and upgrade familiesVersions that must be removed firstBefore it goes on: the preflightCleaning up later: the cleanup taskAdd-ons removed with their product: parent, remove-addonsTaking the place of other products: replacesWildcards: [files.ID]Empty folders: [folder.ID]FeaturesConditions: whenVariablesWindows namesProgram filesLeaving a file at removal: keepGuarding the install folderPaths20.6Command line20.7Diagnostic codes
Part III - Background knowledge
21.1Bits21.2Binary numbers21.3Bytes21.4Hexadecimal21.5Reading a hex dump21.6Units: KB, MB and KiB, MiB21.7Where this is used
22.1One, two, four, eight bytes22.2Byte order: little-endian22.3Negative numbers: two's complement22.4Bit flags22.5Testing and setting a bit: AND, OR22.6Where this is used
23.1Characters and code points23.2ASCII23.3Code pages: one byte, 256 characters23.4UTF-823.5UTF-1623.6The byte order mark23.7Unicode normalization23.8When text looks wrong23.9Where this is used
24.1GUIDsVersion and variantIn text and in bytes24.2HashesHashes in the tutorial's packages24.3GUIDs from hashes: guid --from24.4Where this is used
25.1Why data can be made smaller25.2LZ77: "copy from earlier"25.3Huffman coding: short codes for common symbols25.4Deflate, bit by bit25.5MSZIP: deflate in a cabinet25.6Deflate in an MSIX25.7Where this is used
26.1How a disk stores files26.2An MSI is a file system in a fileSmall streams: the mini streamThe names26.3An MSIX is an archive26.4Why two designs?26.5Where this is used
27.1Tables, rows and columns27.2Primary keys: what makes a row unique27.3Foreign keys: rows that point at rows27.4Keys you give, keys rubrapack makes27.5Storing strings once: the string pool27.6Tables about tables27.7The IDT text format27.8Where this is used
28.1Two keys instead of one28.2Signing and checking28.3Certificates: whose key is this?Names: CN, O, C28.4Chains and trustRevocation28.5Timestamps28.6Where keys live: files and tokensThe thumbprint28.7Where this is used
29.1What an environment variable is29.2The common variablesFoldersNot folders29.3Folders without a variable29.4Three moments29.5Windows Installer's names29.6In rubrapack29.7Where this is used
Part IV - File formats
31.1Sectors31.2Header (first 512 bytes) [spec]31.3FAT, DIFAT, mini FAT [spec]31.4Directory [spec]31.5A simple, deterministic writer31.6Reading safely31.7Worked example: the tutorial's hello.msi
32.1StreamsStream names32.2The string pool: _StringPool and _StringDataCode page32.3System tablesColumn type bits (_Columns.Type)32.4Table streams32.5Transforms (.mst)32.6Patches (.msp)32.7IDT archive files (what MsiDatabaseExport writes)32.8Reading safely32.9Worked example: the tutorial's hello.msi
33.1Layout [spec] [observed]33.2Properties an installer package sets33.3The code page trap - keep summary strings ASCII [observed]33.4Worked example: the tutorial's hello.msi
34.1Tables and columns34.2Property34.3Directory34.4Components, features, files34.5Empty folders34.6Media and the cabinet34.7Major upgrade and downgrade refusal34.8Running an installed program to register and unregister34.9Registry values34.10Shortcuts34.11Removing files and duplicating them34.12Environment variables34.13INI files34.14Searches and launch conditions34.15Services, fonts, permissions34.16Cabinets, administrative images, advertisement34.17Per-user and dual packages34.18Files in use34.19Sequences34.20DialogsChoices during installationSeveral languages in one package34.21What this recipe does not cover yet
35.1Finding the headers [spec]35.2The version resource [spec]35.3What goes into the package [observed]35.4Reading safely
36.1Cabinet layout [spec: MS-CAB]Block checksum [spec]36.2MSZIP [spec: MS-MCI]36.3LZX [spec: MS-PATCH 2, MS-CAB]36.4A deflate encoder in brief [spec: RFC 1951]36.5Worked example: the tutorial's hello.msi
38.1Where the signature lives in a PE file38.2The PE digest38.3The CMS SignedData38.4MSI packages38.5Timestamps38.6ECDSA38.7What Windows reports38.8Worked example: the tutorial's hello.msi
39.1The database opens and decodes39.2The package installs39.3Checks before writing39.4Microsoft's ICE rules [observed]39.5Things that look fine but are not
40.1The ZIP archive40.2The block map (AppxBlockMap.xml)40.3[Content_Types].xml40.4The manifest (AppxManifest.xml)40.5The virtual registry (Registry.dat, User.dat)40.6The virtual file system (VFS\...)40.7The resource index (resources.pri) [observed]40.8Extensions40.9Bundles (.msixbundle)40.10Signatures (AppxSignature.p7x)40.11Installing an unsigned package40.12Worked example: the tutorial's hello.msix