void PrepareStepOn(UpdateStepOn step) { switch (step) { case UpdateStepOn.Checking: ShowFrame(Frame.Checking); break; case UpdateStepOn.UpdateAvailable: ShowFrame(Frame.UpdateInfo); break; case UpdateStepOn.UpdateDownloaded: // set the update step pending (extracting) update.CurrentlyUpdating = UpdateOn.Extracting; needElevation = NeedElevationToUpdate(); // show frame InstallUpdate ShowFrame(Frame.InstallUpdates); // put a checkmark next to downloaded panelDisplaying.UpdateItems[0].Status = UpdateItemStatus.Success; break; case UpdateStepOn.UpdateReadyToInstall: string updtDetailsFilename = Path.Combine(tempDirectory, "updtdetails.udt"); // Try to load the update details file if (File.Exists(updtDetailsFilename)) { updtDetails = UpdateDetails.Load(updtDetailsFilename); } else { throw new Exception("Update details file does not exist."); } // set the update step pending (closing processes & installing files, etc.) update.CurrentlyUpdating = UpdateOn.ClosingProcesses; needElevation = NeedElevationToUpdate(); // show frame InstallUpdate ShowFrame(Frame.InstallUpdates); // put a checkmark next to downloaded panelDisplaying.UpdateItems[0].Status = UpdateItemStatus.Success; // set the "Extracting" text SetStepStatus(1, clientLang.Extract); break; default: throw new Exception("Can't restore from this automatic update state: " + step); } }
void bw_DoWorkInstallSelfUpdate(object sender, DoWorkEventArgs e) { Exception except = null; try { string updtDetailsFilename = Path.Combine(OutputDirectory, "updtdetails.udt"); if (File.Exists(updtDetailsFilename)) { UpdtDetails = UpdateDetails.Load(updtDetailsFilename); } //find self in Path.Combine(OutputDirectory, "base") UpdateFile updateFile = FindNewClient(); //find and forcibly close oldClientLocation KillProcess(OldSelfLoc, FromAutoUpdate); int retriedTimes = 0; while (true) { try { FileAttributes atr = File.GetAttributes(OldSelfLoc); bool resetAttributes = (atr & FileAttributes.Hidden) != 0 || (atr & FileAttributes.ReadOnly) != 0 || (atr & FileAttributes.System) != 0; // remove the ReadOnly & Hidden atributes temporarily if (resetAttributes) { File.SetAttributes(OldSelfLoc, FileAttributes.Normal); } //transfer new client to the directory (Note: this assumes a standalone client - i.e. no dependencies) File.Copy(NewSelfLoc, OldSelfLoc, true); if (resetAttributes) { File.SetAttributes(OldSelfLoc, atr); } } catch (IOException IOEx) { int HResult = Marshal.GetHRForException(IOEx); // if sharing violation if ((HResult & 0xFFFF) == 32) { // sleep for 1 second Thread.Sleep(1000); // stop waiting if cancelled if (IsCancelled()) { break; } // wait a maximum of 30 seconds if (retriedTimes == 30) { throw; } // otherwise, retry file copy ++retriedTimes; continue; } throw; } break; } //Optimize client if necessary if (updateFile != null) { NGenInstall(OldSelfLoc, updateFile); } } catch (Exception ex) { except = ex; } if (IsCancelled() || except != null) { // report cancellation bw.ReportProgress(0, new object[] { -1, -1, "Cancelling update...", ProgressStatus.None, null }); // Delete temporary files if (except != null) { // remove the entire temp directory try { Directory.Delete(OutputDirectory, true); } catch { } } bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except }); } else { bw.ReportProgress(0, new object[] { -1, -1, "Self update complete", ProgressStatus.Success, null }); } }
void bw_DoWorkExtractSelfUpdate(object sender, DoWorkEventArgs e) { Exception except = null; try { if (!Directory.Exists(OutputDirectory)) { Directory.CreateDirectory(OutputDirectory); } //extract downloaded self update ExtractUpdateFile(); try { // remove update file (it's no longer needed) File.Delete(Filename); } catch { } string updtDetailsFilename = Path.Combine(OutputDirectory, "updtdetails.udt"); if (File.Exists(updtDetailsFilename)) { UpdtDetails = UpdateDetails.Load(updtDetailsFilename); } // generate files from patches CreatewyUpdateFromPatch(); //find self in Path.Combine(OutputDirectory, "base") FindNewClient(); } catch (Exception ex) { except = ex; } if (IsCancelled() || except != null) { // report cancellation bw.ReportProgress(0, new object[] { -1, -1, "Cancelling update...", ProgressStatus.None, null }); // Delete temporary files if (except != null) { // remove the entire temp directory try { Directory.Delete(OutputDirectory, true); } catch { } } bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except }); } else { bw.ReportProgress(0, new object[] { -1, -1, "Self update extraction complete", ProgressStatus.Success, null }); } }
void bw_DoWorkSelfUpdate(object sender, DoWorkEventArgs e) { Exception except = null; try { // extract downloaded self update ExtractUpdateFile(); try { // remove update file (it's no longer needed) File.Delete(Filename); } catch { } //find and forcibly close oldClientLocation KillProcess(OldSelfLoc, FromAutoUpdate); string updtDetailsFilename = Path.Combine(OutputDirectory, "updtdetails.udt"); if (File.Exists(updtDetailsFilename)) { UpdtDetails = UpdateDetails.Load(updtDetailsFilename); //remove the file to prevent conflicts with the regular product update File.Delete(updtDetailsFilename); } // generate files from patches CreatewyUpdateFromPatch(); //find self in Path.Combine(OutputDirectory, "base") UpdateFile updateFile = FindNewClient(); int retriedTimes = 0; while (true) { try { FileAttributes atr = File.GetAttributes(OldSelfLoc); bool resetAttributes = (atr & FileAttributes.Hidden) != 0 || (atr & FileAttributes.ReadOnly) != 0 || (atr & FileAttributes.System) != 0; // remove the ReadOnly & Hidden atributes temporarily if (resetAttributes) { File.SetAttributes(OldSelfLoc, FileAttributes.Normal); } //transfer new client to the directory (Note: this assumes a standalone wyUpdate - i.e. no dependencies) File.Copy(NewSelfLoc, OldSelfLoc, true); if (resetAttributes) { File.SetAttributes(OldSelfLoc, atr); } } catch (IOException IOEx) { int HResult = Marshal.GetHRForException(IOEx); // if sharing violation if ((HResult & 0xFFFF) == 32) { // sleep for 1 second Thread.Sleep(1000); // stop waiting if cancelled if (IsCancelled()) { break; } // wait a maximum of 30 seconds if (retriedTimes == 30) { throw; } // otherwise, retry file copy ++retriedTimes; continue; } throw; } break; } // Optimize client if necessary if (updateFile != null) { NGenInstall(OldSelfLoc, updateFile); } //cleanup the client update files to prevent conflicts with the product update File.Delete(NewSelfLoc); Directory.Delete(Path.Combine(OutputDirectory, "base")); } catch (Exception ex) { except = ex; } if (IsCancelled() || except != null) { // report cancellation bw.ReportProgress(0, new object[] { -1, -1, "Cancelling update...", ProgressStatus.None, null }); // Delete temporary files if (except != null && except.GetType() != typeof(PatchApplicationException)) { // remove the entire temp directory try { Directory.Delete(OutputDirectory, true); } catch { } } else { //only 'gut' the folder leaving the server file string[] dirs = Directory.GetDirectories(TempDirectory); foreach (string dir in dirs) { try { Directory.Delete(dir, true); } catch { } } } bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except }); } else { bw.ReportProgress(0, new object[] { -1, -1, "Self update complete", ProgressStatus.Success, null }); } }
void bw_DoWorkUnzip(object sender, DoWorkEventArgs e) { Exception except = null; string updtDetailsFilename = Path.Combine(TempDirectory, "updtdetails.udt"); try { ExtractUpdateFile(); try { // remove update file (it's no longer needed) File.Delete(Filename); } catch { } // Try to load the update details file if (File.Exists(updtDetailsFilename)) { UpdtDetails = UpdateDetails.Load(updtDetailsFilename); } else { throw new Exception("The update details file \"updtdetails.udt\" is missing."); } if (Directory.Exists(Path.Combine(TempDirectory, "patches"))) { // patch the files foreach (UpdateFile file in UpdtDetails.UpdateFiles) { if (file.DeltaPatchRelativePath != null) { if (IsCancelled()) { break; } string tempFilename = Path.Combine(TempDirectory, file.RelativePath); // create the directory to store the patched file if (!Directory.Exists(Path.GetDirectoryName(tempFilename))) { Directory.CreateDirectory(Path.GetDirectoryName(tempFilename)); } while (true) { try { using (FileStream original = File.Open(FixUpdateDetailsPaths(file.RelativePath), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (FileStream patch = File.Open(Path.Combine(TempDirectory, file.DeltaPatchRelativePath), FileMode.Open, FileAccess.Read, FileShare.Read)) using (FileStream target = File.Open(tempFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { VcdiffDecoder.Decode(original, patch, target, file.NewFileAdler32); } } catch (IOException IOEx) { int HResult = Marshal.GetHRForException(IOEx); // if sharing violation if ((HResult & 0xFFFF) == 32) { // notify main window of sharing violation bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.SharingViolation, FixUpdateDetailsPaths(file.RelativePath) }); // sleep for 1 second Thread.Sleep(1000); // stop waiting if cancelled if (IsCancelled()) { break; } // retry file patch continue; } throw new PatchApplicationException("Patch failed to apply to this file: " + FixUpdateDetailsPaths(file.RelativePath) + "\r\n\r\nBecause that file failed to patch, and there's no \"catch-all\" update to download, the update failed to apply. The failure to patch usually happens because the file was modified from the original version. Reinstall the original version of this app.\r\n\r\n\r\nInternal error: " + IOEx.Message); } catch (Exception ex) { throw new PatchApplicationException("Patch failed to apply to this file: " + FixUpdateDetailsPaths(file.RelativePath) + "\r\n\r\nBecause that file failed to patch, and there's no \"catch-all\" update to download, the update failed to apply. The failure to patch usually happens because the file was modified from the original version. Reinstall the original version of this app.\r\n\r\n\r\nInternal error: " + ex.Message); } // the 'last write time' of the patch file is really the 'lwt' of the dest. file File.SetLastWriteTime(tempFilename, File.GetLastWriteTime(Path.Combine(TempDirectory, file.DeltaPatchRelativePath))); break; } } } try { // remove the patches directory (frees up a bit of space) Directory.Delete(Path.Combine(TempDirectory, "patches"), true); } catch { } } } catch (BadPasswordException ex) { except = new BadPasswordException("Could not install the encrypted update because the password did not match."); } catch (Exception ex) { except = ex; } if (IsCancelled() || except != null) { // report cancellation bw.ReportProgress(0, new object[] { -1, -1, "Cancelling update...", ProgressStatus.None, null }); // Delete temporary files if (except != null && except.GetType() != typeof(PatchApplicationException)) { // remove the entire temp directory try { Directory.Delete(OutputDirectory, true); } catch { } } else { //only 'gut' the folder leaving the server file string[] dirs = Directory.GetDirectories(TempDirectory); foreach (string dir in dirs) { // delete everything but the self-update folder (AutoUpdate specific) //Note: this code might be causing the "pyramid of death". TODO: Check. if (Path.GetFileName(dir) == "selfupdate") { continue; } try { Directory.Delete(dir, true); } catch { } } // remove the update details if (File.Exists(updtDetailsFilename)) { File.Delete(updtDetailsFilename); } } bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except }); } else { bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null }); } }