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.
- Edit tu.php to change the database name and the default administrator username + password.
- Upload tu.php to your server.
- 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. - 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