The project file (format 2)
Signature
A JSON object with "format": 2, UTF-8, comments and trailing commas allowed, in the folder of the starter. The starter
takes, in this order:
- the
.jsonfile/RUNCFG <file>names (a plain file name in the starter's folder); - (version 2.3.0 and later)
<name>.bootstrapper.jsonnamed after the starter EXE, when it exists -demo.bootstrapper.jsonfordemo.exe, asdemo.exe.configbelongs todemo.exein .NET; bootstrapper.json.
The starter may be renamed (demo.exe): it reads its folder whatever its name, and the shortcuts ([Starter]) and the entry
under Apps name the renamed file: install, update, start without the source, /list and /uninstall behave the same. In version 2.3.0 and later, several renamed starters share one folder, one per profile, each with its own
project file and without /RUNCFG in a shortcut:
| Starter | Project file | Profile |
|---|---|---|
demo.exe | demo.bootstrapper.json | the users' application (live) |
demo-admin.exe | demo-admin.bootstrapper.json | the administration version |
demo-dev.exe | demo-dev.bootstrapper.json | a developer version |
Each profile needs a product of its own; two project files with the same product key replace each other's installation
on a user's PC. The Apps entry removes the product through the starter at the path it was started from; a starter on a
share that is no longer reachable cannot remove it from there - start /uninstall from a reachable copy of the starter.
Format 1 and format 2 are formats of this file only. The project file of the build tool of WKL Forms Object Library
(access-app.json) is another file with its own format, and the starter never reads it; of a build, the starter reads only
the app-manifest.json the build tool writes into each delivery folder (version.from); its own field format is the
version of the manifest's schema, not one of the formats of this file. Whether an application goes
through format 1 or format 2 is decided by the bootstrapper.json its administrator places next to the starter, not by the
application.
{
"format": 2,
"product": "Checkout",
"display": { "name": "Checkout Pro", "publisher": "Contoso", "copyright": [ "(c) 2026 Contoso" ], "logo": "logo.png" },
"version": { "value": "3.2.1" },
"source": "\\\\server\\share\\checkout",
"deliveryKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...",
"files": [
{ "id": "bin", "source": "bin", "target": "[VersionDir]" },
{ "source": "com\\x86", "target": "[AppDir]\\com", "action": "registerCom", "bitness": "x86" }
],
"registry": [ { "key": "Software\\Contoso\\Checkout", "values": [ { "name": "Home", "data": "[Dir:bin]" } ] } ],
"shortcuts": [ { "folder": "[Programs]\\Contoso", "name": "Checkout", "target": "[Starter]", "arguments": "[RunConfig]" } ],
"fileTypes": [ { "extension": ".checkout", "progId": "Contoso.Checkout", "description": "Sales receipt", "command": "\"[Starter]\" [RunConfig] \"%1\"" } ],
"actions": [ { "when": "beforeInstall", "program": "setup\\vc_redist.x86.exe", "arguments": "/install /quiet /norestart", "successCodes": [ 0, 3010 ] } ],
"conditions": [ { "kind": "dotnet", "value": "Microsoft.WindowsDesktop.App 10.0", "message": ".NET 10 is missing.", "link": "https://dot.net" } ],
"start": { "file": "[VersionDir]\\Checkout.exe", "arguments": "/mode kiosk" },
"keepVersions": 2
}
Summary
What the starter installs for the Windows user, what it registers, which conditions it checks, which programs it runs and what it starts - any program or file, an Access application being one case among others. The starter carries it out without administrator rights, as one transaction with rollback, counted and removable under Settings > Apps.
Property value
| Member | Type | Default | Meaning |
|---|---|---|---|
format | number | - | 2. |
product | text | - | Product key: letters, digits, ., -, _, at most 64. Names the entry WKL.<product> under Apps and the default folder. |
display | object | empty | What the windows and Apps show: name (default the product key), publisher, copyright (lines), authors (lines), logo (PNG, BMP or JPEG in the starter's folder or below it), preparing and starting (texts of the progress window), language (en, de, sl, hr, it; empty: as Office), colorScheme (automatic, light, dark). |
version | object | - | Exactly one of value (for example "3.2.1", two to four numbers) and from: a file in the source - app-manifest.json of an Access delivery (its version; also sets [ManifestFile]) or a program or library (its product version). |
source | text | - | The delivery folder: absolute, a share, or relative to the starter's folder. A relative path resolves against the folder the starter runs from; after an installation from an MSI package that is Program Files (x86)\WKL\<product>, so the project file of a package names a share or an absolute path. |
deliveryKey | text | empty | The publisher's public delivery key (base64, as /new-key prints it). When set, only files signed with it are installed (not the programs of actions); see Signed deliveries. |
appDir | text | [LocalAppData]\WKL\[Product] | [AppDir]. |
versionDir | text | [AppDir]\Frontends\[Version] | [VersionDir]: a folder per delivered version. |
bitness | text | access | Which bitness the entries with bitness follow: access (of Microsoft Access; Windows when none), os, x86, x64. |
files | list | empty | Files of the delivery and where they go; see Files. |
registry | list | empty | Keys below HKEY_CURRENT_USER: key (without the root), view (64 default, 32), bitness, values with name (empty: default value), kind (String, ExpandString, DWord, QWord, MultiString with lines separated by \n), data. |
shortcuts | list | empty | folder ([Desktop], [Programs] or below), name, target, arguments, icon (file with optional ,index), hotkey (for example Ctrl+Alt+K; letters, digits, F1-F24). |
fileTypes | list | empty | File types for the user: extension (with its dot), progId, description, command, icon. |
actions | list | empty | Programs the starter runs; see Actions. |
conditions | list | empty | Checked before anything is installed; see Conditions. |
ini | object | none | An INI file: path (placeholder path ending in .ini), values with section, key, value. Keys that look like passwords are refused. |
start | object | nothing started | file (any program or file; a document opens with its file association), arguments, folder (default the folder of file); for an Access database also runtime (auto: as app-manifest.json says, else for an ACCDE; always; never) and command (the /cmd value). window (from 2.1.0): normal (default) or minimized - the program starts minimized without taking the foreground, for an application that restores its own window once it is ready, for example after its sign-in; Access builds its ribbon and document area while minimized as in a normal start; a document opened through its file association can only be asked for a minimized window, its program decides. splash (from 2.2.0): duration, the minimum display time of the start window as a splash on every start, in milliseconds from the moment it appears, 0 to 10000, default 3000 also when splash is absent. The target starts as the last step, once checking and installing are done and the duration has passed (never a wait added to work that takes longer); the splash closes the moment the target shows its first window (from 2.2.1). 0 turns the splash off (a window then appears only when a start takes longer than 0.8 seconds). environment: variables the started program gets, each name, value (with placeholders, for example [Dir:dotnet-x86]) and optionally bitness (x86, x64); a name once per bitness. The installed version keeps them for a start without the source. |
keepVersions | number | 2 | Versions kept in the user's profile, at least 2. |
Placeholders
Every target the starter writes to (appDir, versionDir, a files target, a shortcut folder, the INI file) is a
placeholder path below a folder of the user; a target outside them, .. in a path, a registry key naming another hive and
an unknown placeholder are refused before anything runs (code 11).
Folders of the user - may begin a target. Before 2.3.0 only [LocalAppData], [AppData], [Documents], [Desktop],
[Programs] and [Startup] existed.
| Placeholder | Folder (example for the user anna) |
|---|---|
[UserProfile] | %USERPROFILE% (C:\Users\anna), for an application in a folder of its own below the profile ([UserProfile]\Demo) |
[LocalAppData] | C:\Users\anna\AppData\Local |
[LocalAppDataLow] | C:\Users\anna\AppData\LocalLow |
[AppData] | C:\Users\anna\AppData\Roaming (follows a roaming profile) |
[UserPrograms] | C:\Users\anna\AppData\Local\Programs, where per-user installers put programs |
[Documents], [Downloads], [Pictures], [Music], [Videos] | The user's libraries, where the user has moved them |
[Desktop], [Favorites], [Templates], [SendTo] | The user's desktop, favorites, document templates and the Send to menu |
[StartMenu], [Programs], [Startup] | The user's start menu, its Programs folder and the Startup folder |
[WklRoot] | [LocalAppData]\WKL |
The libraries and [Downloads], [LocalAppDataLow], [UserPrograms] are read from Windows as known folders; a folder
Windows cannot name on that PC stays without a value, and a target below it is refused like an unknown placeholder.
Folders of the computer - resolve wherever a placeholder may stand that is not a target: start (file, arguments,
folder, environment), actions, conditions and registry data. They never begin a target: writing there needs
administrator rights.
| Placeholder | Folder |
|---|---|
[ProgramFiles], [ProgramFilesX86] | C:\Program Files, C:\Program Files (x86) |
[CommonProgramFiles], [CommonProgramFilesX86] | C:\Program Files\Common Files and its x86 counterpart |
[ProgramData] | C:\ProgramData |
[CommonDocuments], [CommonDesktop], [CommonStartMenu], [CommonPrograms], [CommonStartup] | The folders shared by all users |
[Windows], [System], [SystemX86], [Fonts] | C:\Windows, C:\Windows\System32, C:\Windows\SysWOW64, C:\Windows\Fonts |
Placeholders of the project:
| Placeholder | Value |
|---|---|
[AppDir], [VersionDir] | See above |
[Product], [Version], [Bitness] | Product key, delivered version, x86 or x64 |
[SourceDir] | The source folder |
[Starter] | Full path of the starter EXE |
[StarterDir], [StarterName] | Version 2.3.0 and later: the folder of the starter EXE without a trailing \, and its file name without .exe (demo for demo.exe) - for files the installer package placed beside it, for example "WKL_SETTINGS": "[StarterDir]\[StarterName].ini" in start.environment |
[RunConfig] | /RUNCFG "<file>" when the starter would not find the project file by itself (neither bootstrapper.json nor, in version 2.3.0 and later, the file named after the starter), else empty - for shortcuts and file types that start the starter again |
[Dir:<id>] | The target folder of the files entry with that id |
[ItemVersion] | In a target only: the product version of the entry's versionOf file; for a COM server without that file, the release in its registration.json |
[ManifestFile] | The file of app-manifest.json when version.from names it |
Files
| Member | Default | Meaning |
|---|---|---|
id | none | Name for [Dir:<id>]; used once, or once per bitness. |
source | - | A file, a folder (everything below it, subfolders kept) or a pattern in one folder (bin\*.dll), relative to the source. |
target | - | The target folder. |
action | copy | copy; registerCom (a COM server, registered for the user from registration.json beside it); registerNetCom (a .NET Framework assembly for COM, the same way). |
bitness | both | x86 or x64: installed only for that bitness. |
versionOf | none | A file of the entry whose product version is [ItemVersion]. A COM server (registerCom) needs none: if the field is empty or the named file is missing, for example because the server was renamed after the project file was written, the release in its registration.json applies. |
Files below [VersionDir] belong to their version: placed once, never replaced (a program that writes into its folder keeps
its data), removed with the version. Files anywhere else are shared and counted: the same folder used by two products
stays until the last one goes; a file changed in a later delivery is replaced.
Remarks
Install, update and start
Each start reads the project, checks the conditions, and installs the delivered version when it is new or incomplete: files,
registry values, file types, shortcuts, the INI file, the trusted location (only when start.file is an Access database)
and the entry under Apps, then runs the afterInstall actions, all in one transaction. Then it removes versions beyond
keepVersions (never the started one or the last working one) and starts start.file. A failure on the way rolls
everything back; the codes are those of Error codes of the starter.
When the source cannot be reached (code 12) or its delivery is not trusted (code 51), the installed version starts - the last
working one, else the newest - and the update waits for the next start. A diagnosis (/diagnose) reports the source as it
is.
Signed deliveries
delivery.json in the source lists every file of the delivered version with size and SHA-256; delivery.json.sig beside it
is its signature with the publisher's delivery key (ECDSA P-256). /publish writes both.
| Project | Delivery | Result |
|---|---|---|
deliveryKey set | signed with that key, files as listed | Installed |
deliveryKey set | no manifest, no or another signature, another product or version, a file not listed or changed | Not installed (code 51); the installed version starts |
deliveryKey set | signed, but a lower version than the user ever installed, and withdrawn does not name that version | Not installed (code 52); the installed version starts |
no deliveryKey | delivery.json present | Sizes and hashes checked (code 51 when a file differs) |
no deliveryKey | no delivery.json | Installed as delivered |
Every copy is checked against the manifest after copying, so a file changed between check and copy is not installed either.
Going back. With deliveryKey, the starter compares the delivered version with the highest version the user ever
installed of the product (also after a cleanup or an uninstall), in the order of
Versions. A lower version is installed only when withdrawn in delivery.json names that highest version; /publish /withdraw writes
it (see How to: Publish a signed delivery).
Without deliveryKey a lower version is installed as before.
Not covered. The signature covers the files of files. Programs of actions run directly from the source and are not checked against delivery.json: whoever can write to the source can change them, and they run with the rights of every user who starts the application. A delivery signed earlier stays valid; a starter that installed a higher version refuses it (code 52), but a user who never had a higher version installs it. Protect write access to the source. The trust anchor is the starter's folder with its project file: the delivery key protects a delivery only as long as users cannot change bootstrapper.json, as when the IT installs the starter under Program Files with the MSI. A starter and project file on the share or in the profile can be changed together with the key.
The delivery key is the publisher's own; it costs no code-signing signature. Windows' application control checks Authenticode signatures of programs and libraries only, which the publisher signs with the company certificate as before.
COM servers
The starter never runs a server's own registration (DllRegisterServer, regsvr32) on a user's computer: it writes the
registration from registration.json, which tools\Export-ComRegistration.ps1 captures on the publisher's computer. When two
products bring the same server in different releases, the newer stays registered; when it is removed, the remaining one is
registered again. See How to: Publish a signed delivery.
Actions
| Member | Default | Meaning |
|---|---|---|
when | afterInstall | beforeInstall (before the transaction; a failure installs nothing), afterInstall (inside it; a failure rolls the version back), beforeUninstall (a failure stops the uninstall). |
program | - | A placeholder path, or a path relative to the source. |
arguments | empty | With placeholders. |
once | true | Only when the delivered version is installed for the first time; false: at every start. |
wait | true | Wait (at most 30 minutes) and judge the exit code; false: started is enough. |
successCodes | [0] | Exit codes that count as success, for example [0, 3010] for a setup asking for a restart. |
A program runs with the user's rights; a setup that needs administrator rights fails with its exit code (code 43). Such prerequisites belong into the initial installation by the IT.
beforeUninstall actions run once per uninstall, whatever once says, before anything is removed. Their placeholders
resolve for the version the starter would start last ([VersionDir] is that installed version). A relative program is
taken from the source, which may be gone by then (a share no longer reachable, a delivery removed): the program cannot
start, the uninstall stops with code 43 and nothing is removed. Point such programs at the installed copy
([VersionDir]\...) instead.
Conditions
kind | value | Not met |
|---|---|---|
file | A placeholder path | 35 |
registry | HKLM\...\Key or HKCU\...\Key (the key exists); ...\Key|Name for a value, with expected for its data | 35 |
program | The start of a name under Apps; expected: the lowest DisplayVersion | 35 |
access | Empty (Access at all), or words full, x86, x64 | 20, 22, 21 |
dotnet | Framework name and version, for example Microsoft.WindowsDesktop.App 10.0 | 33 |
odbcDriver, odbcDataSource | The name, in the project's bitness | 34 |
message and link of the condition appear in the diagnostic details.
Format 1
A file with "format": 1 (an Access application, the starter 1.0) is read as a project: the database of app-manifest.json
into [VersionDir] (the folder 1.0 used), the WKL components and ODBC drivers per release and bitness below [WklRoot],
the data source of each driver, the checks of the settings as conditions, the database as start target. Format 1 files
keep working unchanged; a project of format 2 written by the configurator replaces one when needed. Whether the installer
of 2.0 takes a format 1 delivery or it runs the way of 1.0 depends on its components folder: with registration.json next
to the DLL (or without components) the installer, otherwise the way of 1.0 - see
When 2.0 installs and when 1.0 runs.
A file of format 1:
{
"format": 1,
"product": "INSTRA",
"displayName": "INSTRA Verwaltung",
"source": "\\\\server\\apps\\INSTRA\\production",
"components": "components",
"ini": { "file": "TECCUsr.ini", "values": [ { "section": "Properties", "key": "SRV", "value": "sql01" } ] },
"branding": { "logo": "logo.png", "company": "Contoso", "preparing": "Die neue Version wird eingerichtet ..." },
"command": "mandant=2",
"odbcDrivers": [ "ODBC Driver 18 for SQL Server" ],
"language": "",
"colorScheme": "automatic",
"keepVersions": 2
}
| Entry | Meaning |
|---|---|
format | 1. |
product | Key of the application; names the folder in the user's profile (letters, digits, ., -, _). |
displayName | Name in the windows; product when empty. |
source | Folder with app-manifest.json and the delivered file: absolute, a share, or relative to the EXE. |
components | Folder of the WKL components below source (with x86 and x64), registered for the user; empty when installed otherwise. Only WKL Forms Object Library is registered, not WKL Office JSON. |
ini | INI file some older applications read next to themselves; values only, never passwords (keys that look like secrets are refused). |
branding | Company logo (an image file next to the EXE, exchangeable without a new build; the windows show it in place of the DATEC PRO logo they show by default), company name, text while a version is placed. |
command | Value for Access's /cmd (read with Command() in VBA); no quotation marks. |
window | From 2.1.0. normal (default, also when absent) or minimized: Access starts minimized without taking the foreground; the application restores its window itself (for example with DoCmd.Maximize after its sign-in). |
splash | From 2.2.0. duration: as start.splash.duration of format 2 - minimum display time of the start window in milliseconds, 0 to 10000, default 3000; 0 turns the splash off. |
odbcDrivers | ODBC drivers the linked tables need, checked in the bitness of Access: the driver's key under ODBCINST.INI of the computer and its DLL. |
odbcDataSources | From 1.0.1. ODBC data sources (DSNs) the linked tables need - for a driver installed only for the user, which has no ODBCINST.INI entry. A user DSN (HKEY_CURRENT_USER\Software\ODBC\ODBC.INI) comes before a system DSN (read in the bitness of Access); its Driver is a driver name of ODBCINST.INI or the full path of a DLL of the bitness of Access, taken literally (environment variables are not expanded). |
odbc | From 2.0. ODBC drivers the delivery brings for the user, with their data source; see The installer. |
language | Language of the windows: en, de, sl, hr, it; empty for automatic (the user interface language of Office, then of Windows, then English). |
colorScheme | Colors of the windows: automatic (Windows high contrast when it is on, else the Riviera color set of WKL Forms Object Library), light or dark. |
keepVersions | Versions kept in the user's profile, at least 2 (the running one and the last working one). |
Code example
A program that is no Access application, in a folder of its own per version, started with arguments:
{
"format": 2,
"product": "Inventory",
"display": { "name": "Inventory Management", "publisher": "Contoso" },
"version": { "from": "bin\\Inventory.exe" },
"source": "\\\\server\\share\\lager",
"files": [ { "source": "bin", "target": "[VersionDir]" } ],
"shortcuts": [ { "folder": "[Desktop]", "name": "Inventory", "target": "[Starter]", "arguments": "[RunConfig]" } ],
"start": { "file": "[VersionDir]\\Inventory.exe", "arguments": "/user \"[Product]\"" }
}