From 61c717e6d668476717f74fb68e4b690a86917cd4 Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Fri, 16 Sep 2011 14:35:49 +0100 Subject: [PATCH] Temporarily change the current directory to that of the main binary when re-launching the application. This may be required on Windows so that the application can find libraries that it depends upon. --- src/FileUtils.cpp | 35 +++++++++++++++++++++++++++++ src/FileUtils.h | 6 +++++ src/UpdateInstaller.cpp | 49 +++++++++++++++++++++++++++-------------- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/FileUtils.cpp b/src/FileUtils.cpp index d817b65..e1e7efe 100644 --- a/src/FileUtils.cpp +++ b/src/FileUtils.cpp @@ -516,3 +516,38 @@ std::string FileUtils::makeAbsolute(const char* path, const char* basePath) return path; } } + +void FileUtils::chdir(const char* path) throw (IOException) +{ +#ifdef PLATFORM_UNIX + if (::chdir(path) != 0) + { + throw FileUtils::IOException("Unable to change directory"); + } +#else + if (!SetCurrentDirectory(path)) + { + throw FileUtils::IOException("Unable to change directory"); + } +#endif +} + +std::string FileUtils::getcwd() throw (IOException) +{ +#ifdef PLATFORM_UNIX + char path[PATH_MAX]; + if (!::getcwd(path,PATH_MAX)) + { + throw FileUtils::IOException("Failed to get current directory"); + } + return std::string(path); +#else + char path[MAX_PATH]; + if (GetCurrentDirectory(MAX_PATH,path) != 0) + { + throw FileUtils::IOException("Failed to get current directory"); + } + return toUnixPathSeparators(std::string(path)); +#endif +} + diff --git a/src/FileUtils.h b/src/FileUtils.h index 12856ca..ff7afdb 100644 --- a/src/FileUtils.h +++ b/src/FileUtils.h @@ -119,5 +119,11 @@ class FileUtils static std::string makeAbsolute(const char* path, const char* basePath); static void writeFile(const char* path, const char* data, int length) throw (IOException); + + /** Changes the current working directory to @p path */ + static void chdir(const char* path) throw (IOException); + + /** Returns the current working directory of the application. */ + static std::string getcwd() throw (IOException); }; diff --git a/src/UpdateInstaller.cpp b/src/UpdateInstaller.cpp index 866f868..77fa4bc 100644 --- a/src/UpdateInstaller.cpp +++ b/src/UpdateInstaller.cpp @@ -402,27 +402,44 @@ void UpdateInstaller::setObserver(UpdateObserver* observer) void UpdateInstaller::restartMainApp() { - std::string command; - std::list args; - - for (std::vector::const_iterator iter = m_script->filesToInstall().begin(); - iter != m_script->filesToInstall().end(); - iter++) + try { - if (iter->isMainBinary) + std::string command; + std::list args; + + for (std::vector::const_iterator iter = m_script->filesToInstall().begin(); + iter != m_script->filesToInstall().end(); + iter++) { - command = m_installDir + '/' + iter->path; + if (iter->isMainBinary) + { + command = m_installDir + '/' + iter->path; + } + } + + if (!command.empty()) + { + LOG(Info,"Starting main application " + command); + + // change the current directory to that of the application binary, + // so that on Windows the application can find shared libraries + // that it depends on which are in the same directory + std::string appDir = FileUtils::dirname(command.c_str()); + std::string currentDir = FileUtils::getcwd(); + FileUtils::chdir(appDir.c_str()); + + ProcessUtils::runAsync(command,args); + + FileUtils::chdir(currentDir.c_str()); + } + else + { + LOG(Error,"No main binary specified in update script"); } } - - if (!command.empty()) + catch (const std::exception& ex) { - LOG(Info,"Starting main application " + command); - ProcessUtils::runAsync(command,args); - } - else - { - LOG(Error,"No main binary specified in update script"); + LOG(Error,"Unable to restart main app " + std::string(ex.what())); } }