-
Notifications
You must be signed in to change notification settings - Fork 0
Updates
src/update/updater.cpp, src/update/updater.h
Settings → Updates compares this build against the newest release on GitHub, either once at startup or on request. Everything that touches the network runs on a thread of its own; the UI only ever reads a snapshot.
CheckAsync(bool announce) fetches the latest release from the GitHub API and
compares the tag against the version this build reports.
The announce flag is the whole of the difference between the two entry points:
// Whether finding something is worth interrupting anybody for. True only for
// the check made at startup: somebody who pressed "check now" is already
// looking at the answer, and a dialog on top of it is just in the way.
bool announce;-
At startup —
announce = true. When something is found, a notice appears over the picture, once per session whatever you do with it. -
From the button —
announce = false. The answer appears in the tab you are already looking at, and no popup.
That second case was a bug: manually checking used to raise the popup as well, on top of the tab that had already answered.
Nothing is downloaded until you ask. The startup check only asks.
Opens the GitHub release page for the version found (App::OpenReleasePage())
rather than trying to render release notes in the settings window. GitHub already
formats them, and the page is one click from everything else about the release.
The status carries an enum, not a sentence:
enum class UpdateError {
None, NoNetwork, NoServer, NoRequest, NoAnswer, HttpStatus, Transfer,
Unreadable, NoAsset, NoUrl, NotAProgram, WriteFailed, MoveAsideFailed,
InsertFailed,
};The work happens on a thread of its own and the language can be changed at any
time, so the wording is picked where it is shown rather than where it is
raised — UpdateErrorText(const UpdateStatus&) does that in the language
selected right now.
Before this, update errors were German-only strings baked in at the point of failure.
httpStatus is carried alongside, and is meaningful only with
UpdateError::HttpStatus.
Installing replaces CapView.exe itself. Windows will not let a running image be
overwritten, but it will let it be renamed — so:
CapView.exe.new ← the download, written first
CapView.exe → CapView.exe.old (MoveFileExW)
CapView.exe.new → CapView.exe (MoveFileExW)
RemoveLeftovers() deletes .old at the next start. Nothing has to be running
for that to work, and there is no helper process to go missing — which is how
most self-updaters fail.
Is it actually a program?
if (data.size() < 256 * 1024 || data[0] != 'M' || data[1] != 'Z') { … NotAProgram }Every Windows executable starts with those two bytes, and a redirect page or an error document does not. Overwriting the program with an HTML page would be a remarkably annoying way to find that out later.
If the second rename fails, the first is undone.
if (!::MoveFileExW(fresh.c_str(), exe.c_str(), MOVEFILE_REPLACE_EXISTING)) {
::MoveFileExW(old.c_str(), exe.c_str(), MOVEFILE_REPLACE_EXISTING);
…
}A failed update leaves the program exactly as it was rather than gone.
An installation directory the user cannot write to refuses the swap and says so
(MoveAsideFailed / WriteFailed). CapView does not elevate to update itself —
if it is installed somewhere that needs rights to write, replacing it is a
decision for whoever put it there.
RestartIntoNew() starts the freshly installed build and asks the caller to
quit. It returns false when nothing is waiting.
The virtual camera's media source is installed separately and is not replaced by an update — Windows keeps the DLL locked while a camera is in use, and the registration is machine-wide.
That is why the shared memory carries a version number both halves check: after an update the executable and the installed media source genuinely can be from different builds. See Virtual camera.