public void ApplyUpdate(AppInfo appInfo, UpdateInfo info, UpdateHost updateInfoSource) { string lockFile = InstallationSettings.InstallationFolder + "/Updater.lock"; if (File.Exists(lockFile)) { throw new Exception("Could not update: the application folder is already locked by another updater instance."); } else { File.Create(lockFile).Close(); } TriggerProgressEvent(0, "Calculating updater tasks"); FileIndex index = FileIndex.Deserialize(InstallationSettings.InstallationFolder + "/UpdateIndex.dat"); UpdateTask[] tasks = GetUpdaterTasks(appInfo, info, updateInfoSource, index); List <UpdateTask> failedTasks = RunTasks(tasks, true, 10); TriggerProgressEvent(percentageDone, "Retrying failed tasks"); for (int i = 0; i < failedTasks.Count; i++) { UpdateTask task = failedTasks[i]; try { task.Run(); } catch (WebException ex) { if (MessageBox.Show("Updater could not download file: " + ex.Message + "\r\n(" + ex.Data["Target"] + ")", "Failed to download file", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error).Equals(DialogResult.Retry)) { i--; //Retry } else { Application.Exit(); } } catch (UnauthorizedAccessException ex) { if (MessageBox.Show("Updater could access file or folder: " + ex.Message + "\r\n(" + ex.Data["Target"] + ")", "Failed to download file", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error).Equals(DialogResult.Retry)) { i--; //Retry } else { Application.Exit(); } } } TriggerProgressEvent(98, "Updating local file index"); index = new FileIndex(index.appID); index.applicationVersion = info.version; index.files.AddRange(info.fileChecksums.Keys); index.Serialize(InstallationSettings.InstallationFolder + "/UpdateIndex.dat"); File.Delete(lockFile); }
private void StartUpdateCheck() { Updater updater = new Updater(); updater.RetrieveAppInfo((appInfo, hostURL) => { BeginInvoke((Action)(() => { if (appInfo == null) { if (MessageBox.Show(this, "Cannot check for updates: No valid update mirrors online. Launch application anyway?", "Failed to check for updates", MessageBoxButtons.YesNo, MessageBoxIcon.Warning).Equals(DialogResult.Yes)) { Program.LaunchTargetApplication(this); } this.Close(); return; } if (!File.Exists(InstallationSettings.InstallationFolder + "/UpdateIndex.dat")) { if (MessageBox.Show(this, "The installation seems to be corrupt: UpdateIndex.dat is missing. Launch application anyway?", "Failed to check for updates", MessageBoxButtons.YesNo, MessageBoxIcon.Error).Equals(DialogResult.Yes)) { Program.LaunchTargetApplication(this); } this.Close(); return; } FileIndex index = FileIndex.Deserialize(InstallationSettings.InstallationFolder + "/UpdateIndex.dat"); if (index.applicationVersion < appInfo.LatestVersion) { progressLabel.Text = LauncherLocale.Current.Get("Updater.Main.RetrievingUpdateInfo"); double[] newVersions = GetUpdatedVersions(appInfo, index.applicationVersion, appInfo.LatestVersion); MetroForm form; if (newVersions.Length == 1) { form = new SingleUpdateDetailsForm(updater, appInfo, hostURL, newVersions[0]); } else { form = new MultiUpdateDetailsForm(updater, appInfo, hostURL, newVersions); } this.Hide(); form.ShowDialog(); } progressLabel.Text = LauncherLocale.Current.Get("Updater.Main.LaunchApplication"); Program.LaunchTargetApplication(this); this.Close(); })); }); }
public void InstallApplication(Action finishCallback) { if (!Directory.Exists(InstallationSettings.InstallationFolder)) { Directory.CreateDirectory(InstallationSettings.InstallationFolder); } string lockFile = InstallationSettings.InstallationFolder + "/Updater.lock"; if (System.IO.File.Exists(lockFile)) { string message = "The chosen installation folder contains updater files. Installing in this folder may corrupt previous installations. Force installation?"; if (MessageBox.Show(null, message, "Folder contains updater traces", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.Yes) { System.IO.File.Delete(lockFile); } else { Application.Exit(); } } FileIndex newIndex = new FileIndex(LauncherSettings.AppID); newIndex.Serialize(InstallationSettings.InstallationFolder + "/UpdateIndex.dat"); Updater updater = new Updater(); UpdateProgressWindow progressWindow = new UpdateProgressWindow(updater); progressWindow.SetProgress(0, "Retrieving update info"); updater.RetrieveAppInfo((appInfo, host) => { if (appInfo == null) { MessageBox.Show(progressWindow, "Cannot install: No valid download mirrors online.", "Failed to install", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } updater.RetrieveUpdateInfo(appInfo, host, appInfo.LatestVersion, (updateInfo, updateHost) => { Action startUpdate = (() => { if (updateInfo == null) { MessageBox.Show("No valid update info found."); //TODO: Handle this. Should either search for new appInfo host or fail. } progressWindow.SetProgress(20, "Applying updates"); updater.ApplyUpdate(appInfo, updateInfo, updateHost); progressWindow.SetProgress(90, "Registering installation"); try { CreateUninstallRegistryEntry(); SetInstallationFolder(InstallationSettings.InstallationFolder); if (InstallationSettings.CreateDesktopShortcut) { CreateDesktopShortcut(); } if (InstallationSettings.CreateStartMenuEntry) { CreateStartMenuEntry(); } } catch (Exception ex) { MessageBox.Show( "An exception occured while registering the application. \r\n" + ex.Message + "\r\nTo uninstall the application run the updater with -uninstall -forceInstallDir <installfolder>", "Error" ); } progressWindow.Invoke((Action)(() => { progressWindow.Close(); })); InstallationFinishedForm finishedForm = new InstallationFinishedForm(); finishedForm.ShowDialog(); finishCallback.Invoke(); }); Thread updateThread = new Thread(new ThreadStart(startUpdate)); updateThread.Name = "Update thread"; updateThread.IsBackground = true; updateThread.Start(); }); }); progressWindow.Show(); }
public static FileIndex Deserialize(string file) { FileIndex info = JsonConvert.DeserializeObject <FileIndex>(File.ReadAllText(file)); return(info); }
private List <UpdateTask> GetNewFileTasks(AppInfo appInfo, UpdateInfo info, UpdateHost updateInfoSource, FileIndex index) { List <UpdateTask> updateTasks = new List <UpdateTask>(); for (int i = 0; i < info.fileChecksums.Keys.Count; i++) { string curFile = info.fileChecksums.Keys.ElementAt(i); string curLocalFile = InstallationSettings.InstallationFolder + '/' + curFile; if (index.files.Contains(curFile)) { //Already handled file continue; } if (File.Exists(curLocalFile)) { //File exists but is missing in index? string curHash = FileHasher.GetFileChecksum(curLocalFile); string updatedHash; info.fileChecksums.TryGetValue(curFile, out updatedHash); if (updatedHash.Equals(curHash)) { continue; } else { updateTasks.Add(new UpdateTask(TaskType.DownloadReplacementFile, updateInfoSource.GetFileURL(appInfo, info, curFile), curLocalFile)); } } else { updateTasks.Add(new UpdateTask(TaskType.DownloadNewFile, updateInfoSource.GetFileURL(appInfo, info, curFile), curLocalFile)); } } return(updateTasks); }
private List <UpdateTask> GetOldFileTasks(AppInfo appInfo, UpdateInfo info, UpdateHost updateInfoSource, FileIndex index) { List <UpdateTask> updateTasks = new List <UpdateTask>(); for (int i = 0; i < index.files.Count; i++) { string curFile = index.files[i]; string curLocalFile = InstallationSettings.InstallationFolder + '/' + curFile; if (info.fileChecksums.ContainsKey(curFile)) { if (File.Exists(curLocalFile)) { string curHash = FileHasher.GetFileChecksum(curLocalFile); string updatedHash; info.fileChecksums.TryGetValue(curFile, out updatedHash); if (!curHash.Equals(updatedHash)) { updateTasks.Add(new UpdateTask(TaskType.DownloadReplacementFile, updateInfoSource.GetFileURL(appInfo, info, curFile), curLocalFile)); } } else { updateTasks.Add(new UpdateTask(TaskType.DownloadNewFile, updateInfoSource.GetFileURL(appInfo, info, curFile), curLocalFile)); } } else { updateTasks.Add(new UpdateTask(TaskType.DeleteFile, curLocalFile)); } } return(updateTasks); }
private UpdateTask[] GetUpdaterTasks(AppInfo appInfo, UpdateInfo info, UpdateHost updateInfoSource, FileIndex index) { List <UpdateTask> updateTasks = new List <UpdateTask>(); updateTasks.AddRange(GetOldFileTasks(appInfo, info, updateInfoSource, index)); updateTasks.AddRange(GetNewFileTasks(appInfo, info, updateInfoSource, index)); return(updateTasks.ToArray()); }