Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

TU: The Easy Update Library for Your Projects

0.00/5 (No votes)
8 Aug 2019 1  
Live update your Windows project with full or differential updates

Introduction

I hate applications that do not update themselves automatically. Really. Here is a library that will do everything for you automatically. You need a web server capable of running PHP to store the updates and that's all!

Features:

  • Full or differential updates
  • Silent update
  • Compression per item
  • Detached deatabases

Web Server Preparation

You need a decent PHP version. My own server runs PHP 7.3, but the script will work in older versions. It uses SQLite3 to create the database, you can edit it to support MySql or whatever.

  1. Edit tu.php to change the database name and the default administrator username + password.
  2. Upload tu.php to your server.
  3. Go to tu.php?admin. There is a simple admin panel that allows to manage projects. To create a project, you specify a name and an upload password.
  4. When created, the admin panel generates a GUID that is to be put to the Windows application to reference this project.

PHP Admin Panel

The administrator panel shows:

  • Option to vacuum database
  • Option to split database. A split database has the file data outside it, so your SQLite3 database does not grow. 
  • If split, option to join database again.
  • Project list with files containing:
    • Name
    • ID
    • Size
    • Direct Link
    • Option to compress/decompress
    • Number of direct downloads
    • Number of patches
    • Number of checks

The last statistics are reset after uploading.

Windows Application

  • Include tu.hpp
  • Instantiate a TU::TU object:
TU(const char* prjg,const wchar_t* host,const wchar_t* path,
bool SSL = false,unsigned short Port = 0,DWORD flg = 0,const wchar_t* un = 0,
const wchar_t* pwd = 0,const wchar_t* uploadpwd = 0)

Parameters:

  • The unique project GUID created by tu.php admin panel
  • The hostname
  • The path to the PHP script
  • true/false for SSL
  • Optional port (if 0, 80 or 443 are used)
  • Flags for InternetConnect() function
  • Optional username/password for your server
  • The upload password if you plan to upload files

After that, use AddFiles() member to add the files that will be referenced by the library. Each file has a local path and a remote ID (guid):

vector<tuple<wstring, string>> tux;

auto a = L"m.docx";
tux.emplace_back(make_tuple<wstring, 
string>(forward<wstring>(a), string("A44BC1B3-D919-4835-A7D8-FC633EB7B7EC")));
auto b = L"m.pdf";
tux.emplace_back(make_tuple<wstring, 
string>(forward<wstring>(b), string("A44BC1B3-D919-4835-A7D8-FC633EB7B7ED")));
tu.AddFiles(tux);

There is also AddSelf() to add your own executable automatically.

Uploading Updates to Your Server

HRESULT Upload
     (std::function<HRESULT(size_t sent, size_t total, void*)> func = nullptr,void* lp = 0);

HRESULT hr = tu.Upload();

This uses my nice REST library to communicate with the PHP script and ZipUtils to zip the data to upload and that's all. Normally, you won't be calling this function from your app as it will require the upload password and you don't want others to learn that password by sniffing the connection. Usually, you will use a separated "uploader". The function compresses all the items to a ZIP file and sends it to tu.php.

The github repo has a sample "uploader" which uploads items from a XML configuration.

The function accepts an optional callback that is called repeatedly as long as your files are uploading. Return E_FAIL from it to stop the upload.

Checking for Updates

HRESULT Check();
HRESULT hr = tu.Check();

Returns S_OK if all the checked files are up to date, or S_FALSE if any of the files need updating.

Updating

HRESULT DownloadFull(std::function<HRESULT
     (unsigned long long, unsigned long long, void*)> func = nullptr, void* lp = 0);

Automatically downloads all the files that need download and updates them. This function works also with files in use (such as your own application), by moving the current file into a .OLD one, creating a new target, then marking the OLD file for removal. This way, you can self-update easily with a few lines of code and your users won't ever notice it: The next time the application starts, the update will be there.

Differential Checking

Very often, you just need a recompilation because of a simple bug, but your EXE is already 10MB. Isn't it a pity to redownload the entire thing when all that is different is a small portion of your file?

Here, my good DIFF library makes the difference. Actually, TU::Upload() does not only upload your data to the server, but it also calculates a signature for each item and uploads it. Now you can check with:

HRESULT CheckWithSigs(std::function<HRESULT
     (unsigned long long, unsigned long long, void*)> func = nullptr, void* lp = 0);

This function is similar to the simple Check(), but it also downloads the signatures of the files that need to be updated. After this function has returned S_FALSE so that you know that you need updating, call:

HRESULT DownloadDiff(std::function<HRESULT
     (unsigned long long, unsigned long long, void*)> func = nullptr, void* lp = 0);

This function behaves exactly like Download(), but it requests only the portions that are changed from the server, not the entire download. Therefore, using the DIFF library will update your files much faster. The good thing is that it works differentially, not incrementally. This means that, however old the local item is, the function will calculate the different parts of it and request it from the server. Of course, if the local item does not exist, the function will redownload it entirely.

One-Off

void OneOff(const char* r,bool RunNow = false,HICON hIc = LoadIcon(0,IDI_INFORMATION),bool NoDiff = false);

Allows a single EXE to check, download and update itself in one line with an Icon support and a downloading dialog. An update in one line!

The Library

Include tu.hpp (which also includes diff.h, zipall.h and rest.h) and you are ready!

History

  • 4th August, 2019: First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here