From 238169b629fefcdd8c6b4c0461086fef8fe283cc Mon Sep 17 00:00:00 2001 From: Zsolt Szatmari Date: Sat, 11 Apr 2015 14:40:53 +0200 Subject: [PATCH] Allow defining command line arguments for updater There is a new, optional tag which specifies command line arguments to be passed to the installer. This makes it possible to invoke it for silent installation. If no arguments are passed, wxLaunchDefaultApplication() is used to maintain compatibility with previous WinSparkle versions. --- src/appcast.cpp | 3 +++ src/appcast.h | 3 +++ src/ui.cpp | 30 +++++++++++++++++++++++++----- src/ui.h | 2 +- src/updatedownloader.cpp | 2 +- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/appcast.cpp b/src/appcast.cpp index 2e0d63ba..f5382802 100644 --- a/src/appcast.cpp +++ b/src/appcast.cpp @@ -60,6 +60,7 @@ namespace #define ATTR_VERSION NS_SPARKLE_NAME("version") #define ATTR_SHORTVERSION NS_SPARKLE_NAME("shortVersionString") #define ATTR_OS NS_SPARKLE_NAME("os") +#define ATTR_ARGUMENTS NS_SPARKLE_NAME("installerArguments") #define NODE_VERSION ATTR_VERSION // These can be nodes or #define NODE_SHORTVERSION ATTR_SHORTVERSION // attributes. #define OS_MARKER "windows" @@ -167,6 +168,8 @@ void XMLCALL OnStartElement(void *data, const char *name, const char **attrs) ctxt.items[size-1].ShortVersionString = value; else if ( strcmp(name, ATTR_OS) == 0 ) ctxt.items[size-1].Os = value; + else if ( strcmp(name, ATTR_ARGUMENTS) == 0 ) + ctxt.items[size-1].InstallerArguments = value; } } } diff --git a/src/appcast.h b/src/appcast.h index 9b7d67d6..51c902dc 100644 --- a/src/appcast.h +++ b/src/appcast.h @@ -61,6 +61,9 @@ struct Appcast // Minimum OS version required for update std::string MinOSVersion; + // Arguments passed on the the updater executable + std::string InstallerArguments; + /** Initializes the struct with data from XML appcast feed. diff --git a/src/ui.cpp b/src/ui.cpp index e7f03220..03e94e88 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -411,7 +411,7 @@ class UpdateDialog : public WinSparkleDialog // update download progress void DownloadProgress(size_t downloaded, size_t total); // change state into "update downloaded" - void StateUpdateDownloaded(const std::wstring& updateFile); + void StateUpdateDownloaded(const std::wstring& updateFile, const std::string &installerArguments); private: void EnablePulsing(bool enable); @@ -425,6 +425,8 @@ class UpdateDialog : public WinSparkleDialog void OnRunInstaller(wxCommandEvent&); + bool RunInstaller(); + void SetMessage(const wxString& text, int width = MESSAGE_AREA_WIDTH); void ShowReleaseNotes(const Appcast& info); @@ -450,6 +452,8 @@ class UpdateDialog : public WinSparkleDialog Appcast m_appcast; // current update file (only valid after StateUpdateDownloaded) wxString m_updateFile; + // space separated arguments to update file (only valid after StateUpdateDownloaded) + std::string m_installerArguments; // downloader (only valid between OnInstall and OnUpdateDownloaded) UpdateDownloader* m_downloader; @@ -640,7 +644,7 @@ void UpdateDialog::OnRunInstaller(wxCommandEvent&) m_message->SetLabel(_("Launching the installer...")); m_runInstallerButton->Disable(); - if ( !wxLaunchDefaultApplication(m_updateFile) ) + if ( !RunInstaller() ) { wxMessageDialog dlg(this, _("Failed to launch the installer."), @@ -655,6 +659,20 @@ void UpdateDialog::OnRunInstaller(wxCommandEvent&) } } +bool UpdateDialog::RunInstaller() +{ + if (m_installerArguments.empty()) + { + // keep old way of calling updater to not accidentally break any existing code + return wxLaunchDefaultApplication(m_updateFile); + } + else + { + // wxExecute() returns a process id, or zero on failure + long processId = wxExecute(m_updateFile + " " + m_installerArguments); + return processId != 0; + } +} void UpdateDialog::SetMessage(const wxString& text, int width) { @@ -855,13 +873,14 @@ void UpdateDialog::DownloadProgress(size_t downloaded, size_t total) } -void UpdateDialog::StateUpdateDownloaded(const std::wstring& updateFile) +void UpdateDialog::StateUpdateDownloaded(const std::wstring& updateFile, const std::string& installerArguments) { m_downloader->Join(); delete m_downloader; m_downloader = NULL; m_updateFile = updateFile; + m_installerArguments = installerArguments; LayoutChangesGuard guard(this); @@ -1223,7 +1242,7 @@ void App::OnUpdateDownloaded(wxThreadEvent& event) if ( m_win ) { EventPayload payload(event.GetPayload()); - m_win->StateUpdateDownloaded(payload.updateFile); + m_win->StateUpdateDownloaded(payload.updateFile, payload.appcast.InstallerArguments); } } @@ -1391,11 +1410,12 @@ void UI::NotifyDownloadProgress(size_t downloaded, size_t total) /*static*/ -void UI::NotifyUpdateDownloaded(const std::wstring& updateFile) +void UI::NotifyUpdateDownloaded(const std::wstring& updateFile, const Appcast &appcast) { UIThreadAccess uit; EventPayload payload; payload.updateFile = updateFile; + payload.appcast = appcast; uit.App().SendMsg(MSG_UPDATE_DOWNLOADED, &payload); } diff --git a/src/ui.h b/src/ui.h index f34d614c..e16efc3d 100644 --- a/src/ui.h +++ b/src/ui.h @@ -86,7 +86,7 @@ class UI : public Thread /** Notifies the UI that an update was downloaded. */ - static void NotifyUpdateDownloaded(const std::wstring& updateFile); + static void NotifyUpdateDownloaded(const std::wstring& updateFile, const Appcast &appcast); /** Shows the WinSparkle window in "checking for updates..." state. diff --git a/src/updatedownloader.cpp b/src/updatedownloader.cpp index e6281477..4afad80d 100644 --- a/src/updatedownloader.cpp +++ b/src/updatedownloader.cpp @@ -170,7 +170,7 @@ void UpdateDownloader::Run() UpdateDownloadSink sink(*this, tmpdir); DownloadFile(m_appcast.DownloadURL, &sink); sink.Close(); - UI::NotifyUpdateDownloaded(sink.GetFilePath()); + UI::NotifyUpdateDownloaded(sink.GetFilePath(), m_appcast); } catch ( ... ) {