This is how I did it recently. There is a brief overlap of the old program running and the new programming running. It makes use of the trick that you can rename the current executable and bring the new file in place before you shut down the old one. This is not 100% fail safe, but the only way this could "brick" your application is if CopyFile fails.
#include <windows.h>
#include <iostream>
#include <fstream>
void UpgradeService::UpgradeSelf() {
std::string temp = root + "\\myprogram_tmp.exe";
remove(temp.c_str()); // ignore return code
std::string src = upgradeFolder + "\\myprogram.exe";
std::string dst = root + "\\myprogram.exe";
rename(dst.c_str(),temp.c_str());
CopyFile(src.c_str(),dst.c_str(),false);
static char buffer[512];
strcpy(buffer,dst.c_str());
/* CreateProcess API initialization */
STARTUPINFO siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
::CreateProcess(buffer, // application name/path
NULL, // command line (optional)
NULL, // no process attributes (default)
NULL, // default security attributes
false,
CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE,
NULL, // default env
NULL, // default working dir
&siStartupInfo,
&piProcessInfo);
::TerminateProcess( GetCurrentProcess(),0);
::ExitProcess(0); // exit this process
// this does not return.
}