PageRenderTime 26ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main.cpp

https://github.com/Mendeley/Update-Installer
C++ | 201 lines | 161 code | 30 blank | 10 comment | 11 complexity | f81f6bdb4b30e4129a0326f81363d367 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #include "AppInfo.h"
  2. #include "FileUtils.h"
  3. #include "Log.h"
  4. #include "Platform.h"
  5. #include "ProcessUtils.h"
  6. #include "StringUtils.h"
  7. #include "UpdateScript.h"
  8. #include "UpdaterOptions.h"
  9. #include "tinythread.h"
  10. #if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
  11. #include "UpdateDialogGtkFactory.h"
  12. #include "UpdateDialogAscii.h"
  13. #endif
  14. #if defined(PLATFORM_MAC)
  15. #include "MacBundle.h"
  16. #include "UpdateDialogCocoa.h"
  17. #endif
  18. #if defined(PLATFORM_WINDOWS)
  19. #include "UpdateDialogWin32.h"
  20. #endif
  21. #include <iostream>
  22. #include <memory>
  23. #define UPDATER_VERSION "0.16"
  24. UpdateDialog* createUpdateDialog();
  25. void runUpdaterThread(void* arg)
  26. {
  27. #ifdef PLATFORM_MAC
  28. // create an autorelease pool to free any temporary objects
  29. // created by Cocoa whilst handling notifications from the UpdateInstaller
  30. void* pool = UpdateDialogCocoa::createAutoreleasePool();
  31. #endif
  32. try
  33. {
  34. UpdateInstaller* installer = static_cast<UpdateInstaller*>(arg);
  35. installer->run();
  36. }
  37. catch (const std::exception& ex)
  38. {
  39. LOG(Error,"Unexpected exception " + std::string(ex.what()));
  40. }
  41. #ifdef PLATFORM_MAC
  42. UpdateDialogCocoa::releaseAutoreleasePool(pool);
  43. #endif
  44. }
  45. #ifdef PLATFORM_MAC
  46. extern unsigned char Info_plist[];
  47. extern unsigned int Info_plist_len;
  48. extern unsigned char mac_icns[];
  49. extern unsigned int mac_icns_len;
  50. bool unpackBundle(int argc, char** argv)
  51. {
  52. MacBundle bundle(FileUtils::tempPath(),AppInfo::name());
  53. std::string currentExePath = ProcessUtils::currentProcessPath();
  54. if (currentExePath.find(bundle.bundlePath()) != std::string::npos)
  55. {
  56. // already running from a bundle
  57. return false;
  58. }
  59. LOG(Info,"Creating bundle " + bundle.bundlePath());
  60. // create a Mac app bundle
  61. std::string plistContent(reinterpret_cast<const char*>(Info_plist),Info_plist_len);
  62. std::string iconContent(reinterpret_cast<const char*>(mac_icns),mac_icns_len);
  63. bundle.create(plistContent,iconContent,ProcessUtils::currentProcessPath());
  64. std::list<std::string> args;
  65. for (int i = 1; i < argc; i++)
  66. {
  67. args.push_back(argv[i]);
  68. }
  69. ProcessUtils::runSync(bundle.executablePath(),args);
  70. return true;
  71. }
  72. #endif
  73. void setupConsole()
  74. {
  75. #ifdef PLATFORM_WINDOWS
  76. // see http://stackoverflow.com/questions/587767/how-to-output-to-console-in-c-windows
  77. // and http://www.libsdl.org/cgi/docwiki.cgi/FAQ_Console
  78. AttachConsole(ATTACH_PARENT_PROCESS);
  79. freopen( "CON", "w", stdout );
  80. freopen( "CON", "w", stderr );
  81. #endif
  82. }
  83. int main(int argc, char** argv)
  84. {
  85. #ifdef PLATFORM_MAC
  86. void* pool = UpdateDialogCocoa::createAutoreleasePool();
  87. #endif
  88. Log::instance()->open(AppInfo::logFilePath());
  89. #ifdef PLATFORM_MAC
  90. // when the updater is run for the first time, create a Mac app bundle
  91. // and re-launch the application from the bundle. This permits
  92. // setting up bundle properties (such as application icon)
  93. if (unpackBundle(argc,argv))
  94. {
  95. return 0;
  96. }
  97. #endif
  98. UpdaterOptions options;
  99. options.parse(argc,argv);
  100. if (options.showVersion)
  101. {
  102. setupConsole();
  103. std::cout << "Update installer version " << UPDATER_VERSION << std::endl;
  104. return 0;
  105. }
  106. UpdateInstaller installer;
  107. UpdateScript script;
  108. if (!options.scriptPath.empty())
  109. {
  110. script.parse(FileUtils::makeAbsolute(options.scriptPath.c_str(),options.packageDir.c_str()));
  111. }
  112. LOG(Info,"started updater. install-dir: " + options.installDir
  113. + ", package-dir: " + options.packageDir
  114. + ", wait-pid: " + intToStr(options.waitPid)
  115. + ", script-path: " + options.scriptPath
  116. + ", mode: " + intToStr(options.mode));
  117. installer.setMode(options.mode);
  118. installer.setInstallDir(options.installDir);
  119. installer.setPackageDir(options.packageDir);
  120. installer.setScript(&script);
  121. installer.setWaitPid(options.waitPid);
  122. installer.setForceElevated(options.forceElevated);
  123. installer.setAutoClose(options.autoClose);
  124. if (options.mode == UpdateInstaller::Main)
  125. {
  126. LOG(Info, "Showing updater UI - auto close? " + intToStr(options.autoClose));
  127. std::unique_ptr<UpdateDialog> dialog(createUpdateDialog());
  128. dialog->setAutoClose(options.autoClose);
  129. dialog->init(argc, argv);
  130. installer.setObserver(dialog.get());
  131. tthread::thread updaterThread(runUpdaterThread, &installer);
  132. dialog->exec();
  133. updaterThread.join();
  134. }
  135. else
  136. {
  137. installer.run();
  138. }
  139. #ifdef PLATFORM_MAC
  140. UpdateDialogCocoa::releaseAutoreleasePool(pool);
  141. #endif
  142. return 0;
  143. }
  144. UpdateDialog* createUpdateDialog()
  145. {
  146. #if defined(PLATFORM_WINDOWS)
  147. return new UpdateDialogWin32();
  148. #elif defined(PLATFORM_MAC)
  149. return new UpdateDialogCocoa();
  150. #elif defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
  151. UpdateDialog* dialog = UpdateDialogGtkFactory::createDialog();
  152. if (!dialog)
  153. {
  154. dialog = new UpdateDialogAscii();
  155. }
  156. return dialog;
  157. #endif
  158. }
  159. #ifdef PLATFORM_WINDOWS
  160. // application entry point under Windows
  161. int CALLBACK WinMain(HINSTANCE hInstance,
  162. HINSTANCE hPrevInstance,
  163. LPSTR lpCmdLine,
  164. int nCmdShow)
  165. {
  166. int argc = 0;
  167. char** argv;
  168. ProcessUtils::convertWindowsCommandLine(GetCommandLineW(),argc,argv);
  169. return main(argc,argv);
  170. }
  171. #endif