What happens on your users’ PCs

Updated · 7 min read · For developers, IT and security, QA

This page explains what the Omnihorn installer does on a Windows PC after someone runs your setup.exe. It is for developers, QA and IT staff who need to know where files go, when update checks happen, what is verified, how a failed update is undone, and how to script or remove an install.

Where your app is installed

By default your app is installed for the current user in %LOCALAPPDATA%\<app folder>, with no administrator prompt. The folder name comes from the app name in the dashboard. It is fixed at the first install, so renaming the app later never moves an existing installation.

  • If your design allows it, the user can pick another folder on the first install. A chosen parent folder gets its own subfolder for the app, so the installer always owns the folder it installs into.
  • Updates never show the folder choice and never move an installation.
  • The installer keeps its own files in one hidden folder, .omni-installer, inside the install folder. Your build cannot use that name at the top level.
  • The install appears in Windows Apps & features, with your app’s name and icon.

The update check

An update check asks the Omnihorn update service what build the installer’s channel points at. The installer sends its installed version, its channel and, for a private channel, the token or password. It also sends a random per-installation id, which is how the dashboard counts installs without knowing who the user is.

If the channel points at a build that differs from the installed one, that build is the update. This includes an older build, so a rollback on the channel reaches users the same way a release does. When the build has "What’s new" text, the installer window shows it before the update.

Only changed files are downloaded. Before anything is fetched, the installer compares each file’s hash with what is already on disk and skips the ones that match.

How often it checks

TriggerWhen it checksWhat it does
The installer windowEvery time the user opens it.Shows the update and applies it when the user agrees.
The background updaterOnce per Windows start-up, only if the channel’s check interval has passed.Applies the update silently, with no window.
The silent command lineEvery time it is run.Reports, and applies with --update-if-allowed.

The check interval belongs to the channel. The default is 20 hours. You can choose every N hours up to a week, on every start-up, or manual only, in the Check for updates field of Installer Studio. Each answer from the server carries the current interval, so installed copies follow a change after their next check.

The background updater

After the first successful install, the installer adds a per-user start-up entry named Omnihorn Updater (…). It runs once each time Windows starts, then exits. It is not a service and does not stay in memory.

  1. If nothing is installed, or the interval has not passed since the last answered check, it exits without contacting the server.
  2. If the channel is set to manual only, it never checks.
  3. Otherwise it waits a random few minutes, so a whole office of PCs booting at 9:00 does not check at the same second.
  4. It checks, and applies an update with the same silent path the command line uses.
  5. It never starts or restarts your app. The user meets the new version the next time they open it.

If the server asks it to slow down, it waits the time the server asks for before trying again. If the server cannot be reached, it tries again on the next start-up.

What is verified before anything is applied

An update is applied only after every check below passes. If any one fails, nothing in the install folder changes.

  • Signature. The list of files is signed with your app’s own Ed25519 key. The public key is built into the installer, and the installer refuses a list whose signature does not match.
  • Paths. Every file path in the list is checked before any download. Absolute paths, drive letters, .., reserved Windows names and the installer’s own folder are refused, and the whole update fails.
  • File hashes. Every downloaded file’s SHA-256 must match the signed list.
  • Checks at upload. Every build is re-hashed on the server before it can be assigned to a channel, and scanned for malware where the platform has scanning switched on.

See Security for the full model.

Applying an update, and rolling back on failure

Downloaded files are staged first, never written straight into the install folder. Then the update is applied as one step:

  1. Set the current files aside

    Each file being replaced is renamed to a .bak copy.

  2. Move the new files in

    The verified files are moved into place.

  3. Restore on any failure

    If any file cannot be placed, every .bak copy is restored, so the old version keeps working.

  4. Clean up

    The .bak copies are deleted only after every file is in place. Files the new build no longer has are removed.

  5. Record and start

    The new version is recorded, start-up and shortcut choices are reconciled, and the window starts your launch target.

If a file is locked, for example because the old version is still running, it is renamed and cleaned up on the next update or uninstall, and the update still succeeds. Other failures end the attempt: the window shows the error with Retry, the command line exits with code 1, and the background updater tries again after the next interval.

The silent command line

IT staff and scripts can check and update without a window. Run the installer’s executable with:

powershell
# Report only
omnihorn.exe --no-gui --check-update

# Check and apply an update if there is one
omnihorn.exe --no-gui --check-update --update-if-allowed

The result is one line of JSON on standard output, with a status field such as up_to_date, update_available, updated, blocked or error. Progress and logs go to standard error, so a script can parse standard output safely. On a first install, --install-dir <path> chooses the folder.

Exit codeMeaning
0Success: up to date, updates paused by the developer, or uninstall done.
1Error: network, bad token, permission denied, hash mismatch or an unsafe path. Read the error field.
2An update is available (without --update-if-allowed).
3An update was applied. Nothing needs a restart.
4Uninstall with --confirm was cancelled by the user. Nothing was removed.

Uninstall

Users uninstall from Windows Apps & features, which asks Yes or No first. Scripts can run omnihorn.exe --uninstall; add --confirm to show the same question.

  • By default only the files the installer wrote are removed, along with the folders that leaves empty. Documents and data your app created in the folder stay.
  • The background updater’s start-up entry, your app’s start-up entry and the shortcuts the installer created are removed. A shortcut with the same name that someone else made is left alone.
  • --remove-all removes the whole install folder.
  • System and user folders, such as Windows, Program Files, the user profile or Documents, are never deleted, whatever the option.
  • After uninstalling, the window may ask an optional reason, which is sent without the user’s name or email.

When updates are paused

If your workspace goes over its monthly bandwidth, the update service tells installers that updates are paused instead of offering a build. Installed copies keep running the version they have.

WhereWhat the user or script sees
Installer window, first installA full screen saying "Updates are paused".
Installer window, existing installA notice; the installed app keeps working.
Silent command line"status": "blocked" with exit code 0, so scheduled checks do not look like failures.
Background updaterTreated as no update.

Updates resume once the workspace is back within its bandwidth. See pricing for what each plan includes.

›Does installing need administrator rights?

No. The default install is per user, in the user’s local app data folder, and the start-up entry and shortcuts are per user too.

›Will an update restart my app while someone is using it?

No. The background updater applies files and exits without starting your app. The installer window starts your launch target only after an update the user ran from the window.

›What happens if an update fails halfway?

The files that were set aside are restored, so the previous version keeps working. The next check tries again.

›How can I force a check right now on a test PC?

Open the installer window, or run omnihorn.exe --no-gui --check-update --update-if-allowed. Both ignore the check interval.

Something wrong or missing? Tell us.