/// <summary> /// This method shows the update ui and allows to perform the /// update process /// </summary> /// <param name="currentItem"></param> public void ShowUpdateNeededUI(NetSparkleAppCastItem currentItem) { // create the form NetSparkleForm frm = new NetSparkleForm(currentItem, ApplicationIcon, ApplicationWindowIcon); // configure the form frm.TopMost = true; if (HideReleaseNotes) { frm.RemoveReleaseNotesControls(); } // show it DialogResult dlgResult = frm.ShowDialog(); if (dlgResult == DialogResult.No) { // skip this version NetSparkleConfiguration config = new NetSparkleConfiguration(_AppReferenceAssembly); config.SetVersionToSkip(currentItem.Version); } else if (dlgResult == DialogResult.Yes) { // download the binaries InitDownloadAndInstallProcess(currentItem); } }
/// <summary> /// This method will be notified /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { switch (e.ProgressPercentage) { case 1: { // get the current item NetSparkleAppCastItem currentItem = e.UserState as NetSparkleAppCastItem; // show the update ui if (EnableSilentMode == true) { InitDownloadAndInstallProcess(currentItem); } else { ShowUpdateNeededUI(currentItem); } break; } case 0: { ReportDiagnosticMessage(e.UserState.ToString()); break; } } }
/// <summary> /// Constructor /// </summary> /// <param name="sparkle">the sparkle instance</param> /// <param name="item"></param> /// <param name="appIcon">application icon</param> /// <param name="windowIcon">window icon</param> /// <param name="Unattend"><c>true</c> if this is an unattended install</param> public NetSparkleDownloadProgress(Sparkle sparkle, NetSparkleAppCastItem item, Image appIcon, Icon windowIcon, Boolean Unattend) { InitializeComponent(); if (appIcon != null) { imgAppIcon.Image = appIcon; } if (windowIcon != null) { Icon = windowIcon; } // store the item _sparkle = sparkle; _item = item; //_referencedAssembly = referencedAssembly; _unattend = Unattend; // init ui btnInstallAndReLaunch.Visible = false; lblHeader.Text = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version); progressDownload.Maximum = 100; progressDownload.Minimum = 0; progressDownload.Step = 1; // show the right Size = new Size(Size.Width, 107); lblSecurityHint.Visible = false; }
/// <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"></param> /// <returns></returns> public Boolean IsUpdateRequired(NetSparkleConfiguration config, out NetSparkleAppCastItem latestVersion) { // report ReportDiagnosticMessage("Downloading and checking appcast"); // init the appcast NetSparkleAppCast cast = new NetSparkleAppCast(_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); } else { 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); }
private void InitDownloadAndInstallProcess(NetSparkleAppCastItem item) { if (EnableServiceMode) { DownloadAndInstallSync(item); } else { NetSparkleDownloadProgress dlProgress = new NetSparkleDownloadProgress(this, item, _AppReferenceAssembly, ApplicationIcon, ApplicationWindowIcon, EnableSilentMode); dlProgress.ShowDialog(); } }
/// <summary> /// Updates from appcast /// </summary> /// <param name="currentItem">the current (top-most) item in the app-cast</param> private void Update(NetSparkleAppCastItem currentItem) { if (currentItem != null) { // show the update ui if (EnableSilentMode) { InitDownloadAndInstallProcess(currentItem); } else { ShowUpdateNeededUI(currentItem); } } }
public NetSparkleDownloadProgress(Sparkle sparkle, NetSparkleAppCastItem item, String referencedAssembly, Image appIcon, Icon windowIcon, Boolean Unattend) { InitializeComponent(); if (appIcon != null) { imgAppIcon.Image = appIcon; } if (windowIcon != null) { Icon = windowIcon; } // store the item _sparkle = sparkle; _item = item; _referencedAssembly = referencedAssembly; _unattend = Unattend; // init ui btnInstallAndReLaunch.Visible = false; lblHeader.Text = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version); progressDownload.Maximum = 100; progressDownload.Minimum = 0; progressDownload.Step = 1; // show the right Size = new Size(Size.Width, 107); lblSecurityHint.Visible = false; // get the filename of the download lin String[] segments = item.DownloadLink.Split('/'); String fileName = segments[segments.Length - 1]; // get temp path _tempName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName); // start async download WebClient Client = new WebClient(); Client.DownloadProgressChanged += Client_DownloadProgressChanged; Client.DownloadFileCompleted += Client_DownloadFileCompleted; Uri url = new Uri(item.DownloadLink); Client.DownloadFileAsync(url, _tempName); }
/// <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) { NetSparkleConfiguration config = GetApplicationConfig(); // update profile information is needed UpdateSystemProfileInformation(config); // check if update is required NetSparkleAppCastItem latestVersion = null; 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 shows the update ui and allows to perform the /// update process /// </summary> /// <param name="currentItem">the item to show the UI for</param> public void ShowUpdateNeededUI(NetSparkleAppCastItem currentItem) { if (this.UserWindow == null) { // create the form this.UserWindow = new NetSparkleForm(currentItem, ApplicationIcon, ApplicationWindowIcon); } this.UserWindow.CurrentItem = currentItem; if (this.HideReleaseNotes) { this.UserWindow.HideReleaseNotes(); } // clear if already set. this.UserWindow.UserResponded -= new EventHandler(OnUserWindowUserResponded); this.UserWindow.UserResponded += new EventHandler(OnUserWindowUserResponded); this.UserWindow.Show(); }
/// <summary> /// Starts the download process /// </summary> /// <param name="item">the appcast item to download</param> private void InitDownloadAndInstallProcess(NetSparkleAppCastItem item) { // get the filename of the download lin string[] segments = item.DownloadLink.Split('/'); string fileName = segments[segments.Length - 1]; // get temp path _downloadTempFileName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName); if (this.ProgressWindow == null) { this.ProgressWindow = new NetSparkleDownloadProgress(this, item, ApplicationIcon, ApplicationWindowIcon, EnableSilentMode); } else { this.ProgressWindow.InstallAndRelaunch -= new EventHandler(OnProgressWindowInstallAndRelaunch); } this.ProgressWindow.TempFileName = _downloadTempFileName; this.ProgressWindow.InstallAndRelaunch += new EventHandler(OnProgressWindowInstallAndRelaunch); // set up the download client // start async download if (_webDownloadClient != null) { _webDownloadClient.DownloadProgressChanged -= new DownloadProgressChangedEventHandler(this.ProgressWindow.OnClientDownloadProgressChanged); _webDownloadClient.DownloadFileCompleted -= new AsyncCompletedEventHandler(OnWebDownloadClientDownloadFileCompleted); _webDownloadClient = null; } _webDownloadClient = new WebClient { UseDefaultCredentials = true, Proxy = { Credentials = CredentialCache.DefaultNetworkCredentials }, }; _webDownloadClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(this.ProgressWindow.OnClientDownloadProgressChanged); _webDownloadClient.DownloadFileCompleted += new AsyncCompletedEventHandler(OnWebDownloadClientDownloadFileCompleted); Uri url = new Uri(item.DownloadLink); _webDownloadClient.DownloadFileAsync(url, _downloadTempFileName); this.ProgressWindow.ShowDialog(); }
public static bool CheckDSA(Sparkle sparkle, NetSparkleAppCastItem item, String tempName) { Boolean bDSAOk = false; // check if we have a dsa signature in appcast if (item.DSASignature == null || item.DSASignature.Length == 0) { sparkle.ReportDiagnosticMessage("No DSA check needed"); bDSAOk = true; } else { // report sparkle.ReportDiagnosticMessage("Performing DSA check"); // get the assembly if (File.Exists(tempName)) { // check if the file was downloaded successfully String absolutePath = Path.GetFullPath(tempName); if (!File.Exists(absolutePath)) { throw new FileNotFoundException(); } // get the assembly reference from which we start the update progress // only from this trusted assembly the public key can be used Assembly refassembly = System.Reflection.Assembly.GetEntryAssembly(); if (refassembly != null) { // Check if we found the public key in our entry assembly if (NetSparkleDSAVerificator.ExistsPublicKey("NetSparkle_DSA.pub")) { // check the DSA Code and modify the back color NetSparkleDSAVerificator dsaVerifier = new NetSparkleDSAVerificator("NetSparkle_DSA.pub"); bDSAOk = dsaVerifier.VerifyDSASignature(item.DSASignature, tempName); } } } } return(bDSAOk); }
private void DownloadAndInstallSync(NetSparkleAppCastItem item) { // get the filename of the download link String[] segments = item.DownloadLink.Split('/'); String fileName = segments[segments.Length - 1]; // download sync String _tempName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName); // start async download WebClient Client = new WebClient(); Uri url = new Uri(item.DownloadLink); Client.DownloadFile(url, _tempName); if (NetSparkleCheckAndInstall.CheckDSA(this, item, _tempName)) { NetSparkleCheckAndInstall.Install(this, _tempName); } }
/// <summary> /// Constructor /// </summary> /// <param name="item"></param> /// <param name="appIcon"></param> /// <param name="windowIcon"></param> public NetSparkleForm(NetSparkleAppCastItem item, Image appIcon, Icon windowIcon) { InitializeComponent(); // init ui try { NetSparkleBrowser.AllowWebBrowserDrop = false; NetSparkleBrowser.AllowNavigation = false; } catch (Exception) { } _currentItem = item; lblHeader.Text = lblHeader.Text.Replace("APP", item.AppName); lblInfoText.Text = lblInfoText.Text.Replace("APP", item.AppName + " " + item.Version); lblInfoText.Text = lblInfoText.Text.Replace("OLDVERSION", item.AppVersionInstalled); if (item.ReleaseNotesLink != null && item.ReleaseNotesLink.Length > 0) { NetSparkleBrowser.Navigate(item.ReleaseNotesLink); } else { RemoveReleaseNotesControls(); } if (appIcon != null) { imgAppIcon.Image = appIcon; } if (windowIcon != null) { Icon = windowIcon; } this.TopMost = true; }
public NetSparkleDownloadProgress(Sparkle sparkle, NetSparkleAppCastItem item, String referencedAssembly, Image appIcon, Icon windowIcon, Boolean Unattend) { InitializeComponent(); if (appIcon != null) { imgAppIcon.Image = appIcon; } if (windowIcon != null) { Icon = windowIcon; } // store the item _sparkle = sparkle; _item = item; _referencedAssembly = referencedAssembly; _unattend = Unattend; // init ui btnInstallAndReLaunch.Visible = false; lblHeader.Text = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version); progressDownload.Maximum = 100; progressDownload.Minimum = 0; progressDownload.Step = 1; // show the right Size = new Size(Size.Width, 107); lblSecurityHint.Visible = false; // get the filename of the download link String[] segments = item.DownloadLink.Split('/'); String fileName = segments[segments.Length - 1]; //trim url parameters if (fileName.LastIndexOf('?') > 0) { fileName = fileName.Substring(0, fileName.LastIndexOf('?')); } //sanitize filename fileName = MakeValidFileName(fileName); //if no extension present make msi the default extension if (Path.GetExtension(fileName).Length == 0) { fileName += ".msi"; } // get temp path _tempName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName); //check if file already exists and add counter while (File.Exists(_tempName)) { _tempName = Path.GetDirectoryName(_tempName) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(_tempName) + DateTime.Now.ToFileTimeUtc() + Path.GetExtension(_tempName); } // start async download WebClient Client = new WebClient(); Client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Client_DownloadProgressChanged); Client.DownloadFileCompleted += new AsyncCompletedEventHandler(Client_DownloadFileCompleted); Uri url = new Uri(item.DownloadLink); Client.DownloadFileAsync(url, _tempName); }
/// <summary> /// This method will be executed as worker thread /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void _worker_DoWork(object sender, DoWorkEventArgs e) { // store the did run once feature Boolean goIntoLoop = true; Boolean checkTSP = true; Boolean doInitialCheck = _DoInitialCheck; Boolean 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..."); NetSparkleConfiguration 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 NetSparkleAppCastItem latestVersion = null; 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 = nNextUpdateAction.showStandardUserInterface, ApplicationConfig = config, LatestVersion = latestVersion }; if (updateDetected != null) { updateDetected(this, ev); } // check results switch (ev.NextAction) { case nNextUpdateAction.performUpdateUnattended: { ReportDiagnosticMessage("Unattended update whished from consumer"); EnableSilentMode = true; ReportProgress(1, latestVersion); break; } case nNextUpdateAction.prohibitUpdate: { ReportDiagnosticMessage("Update prohibited from consumer"); break; } case nNextUpdateAction.showStandardUserInterface: default: { ReportDiagnosticMessage("Standard UI update whished from consumer"); 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; } else { // 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; continue; } } } while (goIntoLoop); // reset the islooping handle _loopingHandle.Reset(); }
/// <summary> /// Gets the latest version /// </summary> /// <returns>the AppCast item corresponding to the latest version</returns> public NetSparkleAppCastItem GetLatestVersion() { NetSparkleAppCastItem latestVersion = null; // build a http web request stream WebRequest request = WebRequest.Create(_castUrl); request.UseDefaultCredentials = true; request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials; // request the cast and build the stream WebResponse response = request.GetResponse(); using (Stream inputstream = response.GetResponseStream()) { NetSparkleAppCastItem currentItem = null; if (inputstream == null) { return(null); } using (XmlTextReader reader = new XmlTextReader(inputstream)) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.Name) { case itemNode: { currentItem = new NetSparkleAppCastItem(); break; } case releaseNotesLinkNode: { if (currentItem != null) { currentItem.ReleaseNotesLink = reader.ReadString(); currentItem.ReleaseNotesLink = currentItem.ReleaseNotesLink.Trim('\n'); } break; } case enclosureNode: { if (currentItem != null) { currentItem.Version = reader.GetAttribute(versionAttribute); currentItem.DownloadLink = reader.GetAttribute(urlAttribute); currentItem.DSASignature = reader.GetAttribute(dasSignature); } break; } } break; case XmlNodeType.EndElement: switch (reader.Name) { case itemNode: { if (latestVersion == null) { latestVersion = currentItem; } else if (currentItem.CompareTo(latestVersion) > 0) { latestVersion = currentItem; } break; } } break; } } } } // add some other attributes if (latestVersion != null) { latestVersion.AppName = _config.ApplicationName; latestVersion.AppVersionInstalled = _config.InstalledVersion; } // go ahead return(latestVersion); }
public NetSparkleAppCastItem GetLatestVersion() { NetSparkleAppCastItem latestVersion = null; try { // build a http web request stream WebRequest request = HttpWebRequest.Create(_castUrl); // request the cast and build the stream WebResponse response = request.GetResponse(); Stream inputstream = response.GetResponseStream(); NetSparkleAppCastItem currentItem = null; XmlTextReader reader = new XmlTextReader(inputstream); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case itemNode: { currentItem = new NetSparkleAppCastItem(); break; } case releaseNotesLinkNode: { currentItem.ReleaseNotesLink = reader.ReadString(); currentItem.ReleaseNotesLink = currentItem.ReleaseNotesLink.Trim('\n'); break; } case enclosureNode: { currentItem.Version = reader.GetAttribute(versionAttribute); currentItem.DownloadLink = reader.GetAttribute(urlAttribute); currentItem.DSASignature = reader.GetAttribute(dasSignature); break; } } } else if (reader.NodeType == XmlNodeType.EndElement) { switch (reader.Name) { case itemNode: { if (latestVersion == null) { latestVersion = currentItem; } else if (currentItem.CompareTo(latestVersion) > 0) { latestVersion = currentItem; } break; } } } } // add some other attributes latestVersion.AppName = _config.ApplicationName; latestVersion.AppVersionInstalled = _config.InstalledVersion; } catch (Exception) { } // go ahead return(latestVersion); }