Updater tool

Molflow and Synrad now have a lightweight updater tool

2017-11-29 11_48_03-SynRad+ 1.4.18 (Nov 29 2017) [].png

  • It runs in the background
  • It extracts updates to an adjacent folder, not overwriting anything
  • It doesn't connect to the internet without permission
  • It only asks the user to check for updates after the third app start
  • It provides telemetry to identify update errors, see later about privacy

It queries the available versions listed in an XML file on this website, and if a new version is found, it lists the changelog and offers the user to update.

2017-11-29 11_52_23-Molflow+ 2.6.61 (Nov 29 2017) [].png

The update process happens in the background, and a log window allows to follow it:

2017-11-29 11_52_38-Molflow+ 2.6.61 (Nov 29 2017) [].png

In case of success, the new version is extracted adjacent to the actual folder, and the config file (containing preferences and the recent file list) is copied so you can resume your work more easily.

Privacy

We have set up a Google Analytics project to have anonymous information about the update process (identify when a certain version fails for a large number of users, etc.). It sends an event to the server in the following two cases:

  • When the updater checks for updates (once at program startup, if you have allowed it)
  • When you request an update to be downloaded, and when the update process is finished (with error or success)

Along with the event the following information is sent

  • The current app version (example: Molflow_2.6.61)
  • The event category (examples: updateCheck, folderMoveError, zipExtractError, updateSuccess)
  • A unique identifier (example: 9Sb7Yf1zqAr). This is a 10-15 character long hash, similar to a browser cookie, and its purpose is to distinguish individual users (i.e. to know whether one user had a specific error 10 times or 10 users 1-1 time). This identifier is generated from the windows computer and username through a hash function using the modulo operation: it means that on a certain computer it is always the same, however it is impossible to get the computer or user name from the hash. You can check your own hash code in the app folder's updater_config.xml file.

The updater module runs as a separate, background thread. It cannot access the main app, thus it doesn't know what you are doing, neither the file you are working on. It reports only update checks, update errors and update successes. It connects to the internet only at program startup (if you have allowed it explicitly) and when you ask to download a new version.

For complete transparency, the hashing code is below, as well as the whole updater source code:

AppUpdater.h
AppUpdater.cpp

std::string AppUpdater::GenerateUserId() {
    char computerName[1024];
    char userName[1024];
    DWORD size = 1024;
    GetComputerName(computerName, &size);
    GetUserName(userName, &size);
    std::string id = computerName;
    id += "/";
    id += userName;

    //Create hash code from computer name
    //Hash algorithm source: http://www.cse.yorku.ca/~oz/hash.html
    size_t hashCode = 5381;
    int c;
    size_t index = 0;
    while (c = id.c_str()[index++]) {
        hashCode = ((hashCode << 5) + hashCode) + c; /* hash * 33 + c */
    }

    //Convert hash number to alphanumerical hash (base62)
    std::string alphaNum =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

    std::string userId = "";
    while (hashCode > 0) {
        size_t dividend = (size_t)(hashCode / alphaNum.length());
        size_t remainder = hashCode - dividend*alphaNum.length();
        hashCode = dividend;
        userId = alphaNum[remainder] + userId;
    }

    return userId;
}