/// <summary> /// This method checks if an update is required. During this process the appcast /// will be downloaded and checked against the reference assembly. Ensure that /// the calling process has access to the internet and read access to the /// reference assembly. This method is also called from the background loops. /// </summary> /// <param name="config">the configuration</param> /// <param name="latestVersion">returns the latest version</param> /// <returns><c>true</c> if an update is required</returns> public bool IsUpdateRequired(KryptonSparkleConfiguration config, out KryptonSparkleAppCastItem latestVersion) { // report ReportDiagnosticMessage("Downloading and checking appcast"); // init the appcast KryptonSparkleAppCast cast = new KryptonSparkleAppCast(_AppCastUrl, config); // check if any updates are available try { latestVersion = cast.GetLatestVersion(); } catch (Exception e) { // show the exeception message ReportDiagnosticMessage("Error during app cast download: " + e.Message); // just null the version info latestVersion = null; } if (latestVersion == null) { ReportDiagnosticMessage("No version information in app cast found"); return(false); } ReportDiagnosticMessage("Lastest version on the server is " + latestVersion.Version); // set the last check time ReportDiagnosticMessage("Touch the last check timestamp"); config.TouchCheckTime(); // check if the available update has to be skipped if (latestVersion.Version.Equals(config.SkipThisVersion)) { ReportDiagnosticMessage("Latest update has to be skipped (user decided to skip version " + config.SkipThisVersion + ")"); return(false); } // check if the version will be the same then the installed version Version v1 = new Version(config.InstalledVersion); Version v2 = new Version(latestVersion.Version); if (v2 <= v1) { ReportDiagnosticMessage("Installed version is valid, no update needed (" + config.InstalledVersion + ")"); return(false); } // ok we need an update return(true); }
/// <summary> /// Called when the user responds to the "skip, later, install" question. /// </summary> /// <param name="sender">not used.</param> /// <param name="e">not used.</param> void OnUserWindowUserResponded(object sender, EventArgs e) { if (this.UserWindow.Result == DialogResult.No) { // skip this version KryptonSparkleConfiguration config = GetApplicationConfig(); config.SetVersionToSkip(this.UserWindow.CurrentItem.Version); } else if (this.UserWindow.Result == DialogResult.Yes) { // download the binaries InitDownloadAndInstallProcess(this.UserWindow.CurrentItem); } }
/// <summary> /// Does a one-off check for updates /// </summary> /// <param name="isUserInterfaceShown"><c>true</c> if the user interface is to be shown.</param> public bool CheckForUpdates(bool isUserInterfaceShown) { KryptonSparkleConfiguration config = GetApplicationConfig(); // update profile information is needed UpdateSystemProfileInformation(config); // check if update is required KryptonSparkleAppCastItem latestVersion; if (IsUpdateRequired(config, out latestVersion)) { // show the update window ReportDiagnosticMessage("Update needed from version " + config.InstalledVersion + " to version " + latestVersion.Version); // send notification if needed UpdateDetectedEventArgs ev = new UpdateDetectedEventArgs { NextAction = NextUpdateAction.ShowStandardUserInterface, ApplicationConfig = config, LatestVersion = latestVersion }; if (UpdateDetected != null) { UpdateDetected(this, ev); } // check results if (isUserInterfaceShown) { switch (ev.NextAction) { case NextUpdateAction.PerformUpdateUnattended: EnableSilentMode = true; Update(latestVersion); break; case NextUpdateAction.ProhibitUpdate: break; case NextUpdateAction.ShowStandardUserInterface: default: Update(latestVersion); break; } } return(true); } return(false); }
/// <summary> /// This method updates the profile information which can be sended to the server if enabled /// </summary> /// <param name="config">the configuration</param> public void UpdateSystemProfileInformation(KryptonSparkleConfiguration config) { // check if profile data is enabled if (!EnableSystemProfiling) { return; } // check if we need an update if (DateTime.Now - config.LastProfileUpdate < new TimeSpan(7, 0, 0, 0)) { return; } // touch the profile update time config.TouchProfileTime(); // start the profile thread Thread t = new Thread(ProfileDataThreadStart); t.Start(config); }
/// <summary> /// Profile data thread /// </summary> /// <param name="obj">the configuration object</param> private void ProfileDataThreadStart(object obj) { try { if (SystemProfileUrl != null) { // get the config KryptonSparkleConfiguration config = obj as KryptonSparkleConfiguration; // collect data KryptonSparkleDeviceInventory inv = new KryptonSparkleDeviceInventory(config); inv.CollectInventory(); // build url String requestUrl = inv.BuildRequestUrl(SystemProfileUrl + "?"); // perform the webrequest HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest; if (request != null) { request.UseDefaultCredentials = true; request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials; using (WebResponse response = request.GetResponse()) { // close the response response.Close(); } } } } catch (Exception ex) { // No exception during data send ReportDiagnosticMessage(ex.Message); } }
public KryptonSparkleDeviceInventory(KryptonSparkleConfiguration config) { _config = config; }
/// <summary> /// Constructor /// </summary> /// <param name="castUrl">the URL of the appcast file</param> /// <param name="config">the current configuration</param> public KryptonSparkleAppCast(string castUrl, KryptonSparkleConfiguration config) { _config = config; _castUrl = castUrl; }
/// <summary> /// This method will be executed as worker thread /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnWorkerDoWork(object sender, DoWorkEventArgs e) { // store the did run once feature bool goIntoLoop = true; bool checkTSP = true; bool doInitialCheck = _DoInitialCheck; bool isInitialCheck = true; // start our lifecycles do { // set state Boolean bUpdateRequired = false; // notify if (CheckLoopStarted != null) { CheckLoopStarted(this); } // report status if (doInitialCheck == false) { ReportDiagnosticMessage("Initial check prohibited, going to wait"); doInitialCheck = true; goto WaitSection; } // report status ReportDiagnosticMessage("Starting update loop..."); // read the config ReportDiagnosticMessage("Reading config..."); KryptonSparkleConfiguration config = GetApplicationConfig(); // calc CheckTasp Boolean checkTSPInternal = checkTSP; if (isInitialCheck && checkTSPInternal) { checkTSPInternal = !_ForceInitialCheck; } // check if it's ok the recheck to software state if (checkTSPInternal) { TimeSpan csp = DateTime.Now - config.LastCheckTime; if (csp < _CheckFrequency) { ReportDiagnosticMessage(String.Format("Update check performed within the last {0} minutes!", _CheckFrequency.TotalMinutes)); goto WaitSection; } } else { checkTSP = true; } // when sparkle will be deactivated wait an other cycle if (config.CheckForUpdate == false) { ReportDiagnosticMessage("Check for updates disabled"); goto WaitSection; } // update the runonce feature goIntoLoop = !config.DidRunOnce; // update profile information is needed UpdateSystemProfileInformation(config); // check if update is required KryptonSparkleAppCastItem latestVersion; bUpdateRequired = IsUpdateRequired(config, out latestVersion); if (!bUpdateRequired) { goto WaitSection; } // show the update window ReportDiagnosticMessage("Update needed from version " + config.InstalledVersion + " to version " + latestVersion.Version); // send notification if needed UpdateDetectedEventArgs ev = new UpdateDetectedEventArgs { NextAction = NextUpdateAction.ShowStandardUserInterface, ApplicationConfig = config, LatestVersion = latestVersion }; if (UpdateDetected != null) { UpdateDetected(this, ev); } // check results switch (ev.NextAction) { case NextUpdateAction.PerformUpdateUnattended: { ReportDiagnosticMessage("Unattended update whished from consumer"); EnableSilentMode = true; _worker.ReportProgress(1, latestVersion); break; } case NextUpdateAction.ProhibitUpdate: { ReportDiagnosticMessage("Update prohibited from consumer"); break; } case NextUpdateAction.ShowStandardUserInterface: default: { ReportDiagnosticMessage("Standard UI update whished from consumer"); _worker.ReportProgress(1, latestVersion); break; } } WaitSection: // reset initialcheck isInitialCheck = false; // notify if (CheckLoopFinished != null) { CheckLoopFinished(this, bUpdateRequired); } // report wait statement ReportDiagnosticMessage(String.Format("Sleeping for an other {0} minutes, exit event or force update check event", _CheckFrequency.TotalMinutes)); // wait for if (!goIntoLoop) { break; } // build the event array WaitHandle[] handles = new WaitHandle[1]; handles[0] = _exitHandle; // wait for any int i = WaitHandle.WaitAny(handles, _CheckFrequency); if (WaitHandle.WaitTimeout == i) { ReportDiagnosticMessage(String.Format("{0} minutes are over", _CheckFrequency.TotalMinutes)); continue; } // check the exit hadnle if (i == 0) { ReportDiagnosticMessage("Got exit signal"); break; } // check an other check needed if (i == 1) { ReportDiagnosticMessage("Got force update check signal"); checkTSP = false; } } while (goIntoLoop); // reset the islooping handle _loopingHandle.Reset(); }