mirror of
https://github.com/etlegacy/Update-Installer.git
synced 2025-01-22 23:41:10 +00:00
When re-launching the application after an update is installed, do it from a non-elevated process.
Previously the application was restarted from the main install process, which may have been elevated. The main application must be started from a non-elevated updater/updater.exe process otherwise the main app will inherit the elevated status from its parent. * Modify ProcessUtils::runElevated() to return the status code of the process * Change UpdateInstaller to run the main installation synchronously from the initial updater process in the case where elevation is not required. * Remove calls in main.cpp to relaunch the main application after the UI is closed.
This commit is contained in:
parent
d705095fe9
commit
098c9cb194
4 changed files with 63 additions and 30 deletions
|
@ -71,15 +71,15 @@ void ProcessUtils::runAsync(const std::string& executable,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessUtils::runElevated(const std::string& executable,
|
int ProcessUtils::runElevated(const std::string& executable,
|
||||||
const std::list<std::string>& args)
|
const std::list<std::string>& args)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
runElevatedWindows(executable,args);
|
return runElevatedWindows(executable,args);
|
||||||
#elif defined(PLATFORM_MAC)
|
#elif defined(PLATFORM_MAC)
|
||||||
runElevatedMac(executable,args);
|
return runElevatedMac(executable,args);
|
||||||
#elif defined(PLATFORM_LINUX)
|
#elif defined(PLATFORM_LINUX)
|
||||||
runElevatedLinux(executable,args);
|
return runElevatedLinux(executable,args);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ bool ProcessUtils::waitForProcess(PLATFORM_PID pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
void ProcessUtils::runElevatedLinux(const std::string& executable,
|
int ProcessUtils::runElevatedLinux(const std::string& executable,
|
||||||
const std::list<std::string>& args)
|
const std::list<std::string>& args)
|
||||||
{
|
{
|
||||||
std::string sudoMessage = FileOps::fileName(executable.c_str()) + " needs administrative privileges. Please enter your password.";
|
std::string sudoMessage = FileOps::fileName(executable.c_str()) + " needs administrative privileges. Please enter your password.";
|
||||||
|
@ -152,9 +152,11 @@ void ProcessUtils::runElevatedLinux(const std::string& executable,
|
||||||
int result = ProcessUtils::runSync(sudoBinary,sudoArgs);
|
int result = ProcessUtils::runSync(sudoBinary,sudoArgs);
|
||||||
if (result != 255)
|
if (result != 255)
|
||||||
{
|
{
|
||||||
|
return result;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return RUN_ELEVATED_FAILED;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -245,10 +247,13 @@ void ProcessUtils::runElevatedMac(const std::string& executable,
|
||||||
{
|
{
|
||||||
LOG(Info,"elevated process succeded with pid " + intToStr(childPid));
|
LOG(Info,"elevated process succeded with pid " + intToStr(childPid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return childStatus;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(Error,"failed to launch elevated process " + intToStr(status));
|
LOG(Error,"failed to launch elevated process " + intToStr(status));
|
||||||
|
return RUN_ELEVATED_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we want to know more information about what has happened:
|
// If we want to know more information about what has happened:
|
||||||
|
@ -262,13 +267,18 @@ void ProcessUtils::runElevatedMac(const std::string& executable,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(Error,"failed to get rights to launch elevated process. status: " + intToStr(status));
|
LOG(Error,"failed to get rights to launch elevated process. status: " + intToStr(status));
|
||||||
|
return RUN_ELEVATED_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return RUN_ELEVATED_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
void ProcessUtils::runElevatedWindows(const std::string& executable,
|
int ProcessUtils::runElevatedWindows(const std::string& executable,
|
||||||
const std::list<std::string>& arguments)
|
const std::list<std::string>& arguments)
|
||||||
{
|
{
|
||||||
std::string args;
|
std::string args;
|
||||||
|
@ -304,10 +314,14 @@ void ProcessUtils::runElevatedWindows(const std::string& executable,
|
||||||
if (!ShellExecuteEx(&executeInfo))
|
if (!ShellExecuteEx(&executeInfo))
|
||||||
{
|
{
|
||||||
LOG(Error,"Failed to start with admin priviledges using ShellExecuteEx()");
|
LOG(Error,"Failed to start with admin priviledges using ShellExecuteEx()");
|
||||||
return;
|
return RUN_ELEVATED_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForSingleObject(executeInfo.hProcess, INFINITE);
|
WaitForSingleObject(executeInfo.hProcess, INFINITE);
|
||||||
|
|
||||||
|
// this assumes the process succeeded - we need to check whether
|
||||||
|
// this is actually the case.
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,14 @@
|
||||||
class ProcessUtils
|
class ProcessUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum Errors
|
||||||
|
{
|
||||||
|
/** Status code returned by runElevated() if launching
|
||||||
|
* the elevated process fails.
|
||||||
|
*/
|
||||||
|
RUN_ELEVATED_FAILED = 255
|
||||||
|
};
|
||||||
|
|
||||||
static PLATFORM_PID currentProcessId();
|
static PLATFORM_PID currentProcessId();
|
||||||
|
|
||||||
static std::string currentProcessPath();
|
static std::string currentProcessPath();
|
||||||
|
@ -18,7 +26,13 @@ class ProcessUtils
|
||||||
static void runAsync(const std::string& executable,
|
static void runAsync(const std::string& executable,
|
||||||
const std::list<std::string>& args);
|
const std::list<std::string>& args);
|
||||||
|
|
||||||
static void runElevated(const std::string& executable,
|
/** Run a process with administrative privileges and return the
|
||||||
|
* status code of the process, or 0 on Windows.
|
||||||
|
*
|
||||||
|
* Returns RUN_ELEVATED_FAILED if the elevated process could
|
||||||
|
* not be started.
|
||||||
|
*/
|
||||||
|
static int runElevated(const std::string& executable,
|
||||||
const std::list<std::string>& args);
|
const std::list<std::string>& args);
|
||||||
|
|
||||||
static bool waitForProcess(PLATFORM_PID pid);
|
static bool waitForProcess(PLATFORM_PID pid);
|
||||||
|
@ -32,11 +46,11 @@ class ProcessUtils
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void runElevatedLinux(const std::string& executable,
|
static int runElevatedLinux(const std::string& executable,
|
||||||
const std::list<std::string>& args);
|
const std::list<std::string>& args);
|
||||||
static void runElevatedMac(const std::string& executable,
|
static int runElevatedMac(const std::string& executable,
|
||||||
const std::list<std::string>& args);
|
const std::list<std::string>& args);
|
||||||
static void runElevatedWindows(const std::string& executable,
|
static int runElevatedWindows(const std::string& executable,
|
||||||
const std::list<std::string>& args);
|
const std::list<std::string>& args);
|
||||||
|
|
||||||
static PLATFORM_PID runAsyncUnix(const std::string& executable,
|
static PLATFORM_PID runAsyncUnix(const std::string& executable,
|
||||||
|
|
|
@ -98,20 +98,40 @@ void UpdateInstaller::run() throw ()
|
||||||
args.push_back("--wait");
|
args.push_back("--wait");
|
||||||
args.push_back(intToStr(ProcessUtils::currentProcessId()));
|
args.push_back(intToStr(ProcessUtils::currentProcessId()));
|
||||||
|
|
||||||
|
int installStatus = 0;
|
||||||
if (!checkAccess())
|
if (!checkAccess())
|
||||||
{
|
{
|
||||||
LOG(Info,"Insufficient rights to install app to " + m_installDir + " requesting elevation");
|
LOG(Info,"Insufficient rights to install app to " + m_installDir + " requesting elevation");
|
||||||
|
|
||||||
// start a copy of the updater with admin rights
|
// start a copy of the updater with admin rights
|
||||||
ProcessUtils::runElevated(updaterPath,args);
|
installStatus = ProcessUtils::runElevated(updaterPath,args);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(Info,"Sufficient rights to install app - restarting with same permissions");
|
LOG(Info,"Sufficient rights to install app - restarting with same permissions");
|
||||||
|
installStatus = ProcessUtils::runSync(updaterPath,args);
|
||||||
// TODO - Change this to run synchronously
|
|
||||||
ProcessUtils::runAsync(updaterPath,args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (installStatus == 0)
|
||||||
|
{
|
||||||
|
LOG(Info,"Update install completed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(Error,"Update install failed with status " + intToStr(installStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
// restart the main application - this is currently done
|
||||||
|
// regardless of whether the installation succeeds or not
|
||||||
|
restartMainApp();
|
||||||
|
|
||||||
|
// clean up files created by the updater
|
||||||
|
std::list<std::string> cleanupArgs = updaterArgs();
|
||||||
|
cleanupArgs.push_back("--mode");
|
||||||
|
cleanupArgs.push_back("cleanup");
|
||||||
|
cleanupArgs.push_back("--wait");
|
||||||
|
cleanupArgs.push_back(intToStr(ProcessUtils::currentProcessId()));
|
||||||
|
ProcessUtils::runAsync(updaterPath,cleanupArgs);
|
||||||
}
|
}
|
||||||
else if (m_mode == Main)
|
else if (m_mode == Main)
|
||||||
{
|
{
|
||||||
|
@ -152,13 +172,6 @@ void UpdateInstaller::run() throw ()
|
||||||
{
|
{
|
||||||
m_observer->updateFinished();
|
m_observer->updateFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<std::string> args = updaterArgs();
|
|
||||||
args.push_back("--mode");
|
|
||||||
args.push_back("cleanup");
|
|
||||||
args.push_back("--wait");
|
|
||||||
args.push_back(intToStr(ProcessUtils::currentProcessId()));
|
|
||||||
ProcessUtils::runAsync(updaterPath,args);
|
|
||||||
}
|
}
|
||||||
else if (m_mode == Cleanup)
|
else if (m_mode == Cleanup)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,15 +94,9 @@ void runWithUi(int argc, char** argv, UpdateInstaller* installer)
|
||||||
tthread::thread updaterThread(runUpdaterThread,installer);
|
tthread::thread updaterThread(runUpdaterThread,installer);
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
updaterThread.join();
|
updaterThread.join();
|
||||||
|
|
||||||
if (dialog.restartApp())
|
|
||||||
{
|
|
||||||
installer->restartMainApp();
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
// no UI available - do a silent install
|
// no UI available - do a silent install
|
||||||
installer->run();
|
installer->run();
|
||||||
installer->restartMainApp();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -116,7 +110,6 @@ void runWithUi(int argc, char** argv, UpdateInstaller* installer)
|
||||||
tthread::thread updaterThread(runUpdaterThread,installer);
|
tthread::thread updaterThread(runUpdaterThread,installer);
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
updaterThread.join();
|
updaterThread.join();
|
||||||
installer->restartMainApp();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -141,6 +134,5 @@ void runWithUi(int argc, char** argv, UpdateInstaller* installer)
|
||||||
tthread::thread updaterThread(runUpdaterThread,installer);
|
tthread::thread updaterThread(runUpdaterThread,installer);
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
updaterThread.join();
|
updaterThread.join();
|
||||||
installer->restartMainApp();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue