private void ThreadWorkProc() { Exception resultException = null; UpdateAction updateAction = UpdateAction.Undefined; Version currentVersion = null; bool applicationCloseRequired = false; // Do the work try { CheckToCancel(); UpdateApplicationManifest appManifest = GetApplicationManifest(); CheckToCancel(); DoStatusCallback(-1, "Determining update actions ..."); Version existingVersion; updateAction = GetUpdateAction(appManifest, out existingVersion); currentVersion = existingVersion; if (updateAction == UpdateAction.None) { LOG.Debug("ThreadWorkProc: Exiting thread, updateAction == UpdateAction.None"); } else { CheckToCancel(); LOG.Debug("ThreadWorkProc: Performing {0} from version {1} to version {2}", updateAction.ToString(), (existingVersion == null) ? "Unknown" : existingVersion.ToString(), (appManifest.CurrentDatabaseVersion == null) ? "Not specified" : appManifest.CurrentDatabaseVersion.ToString()); if (EnumUtils.IsFlagSet(updateAction, UpdateAction.FullRefresh)) { currentVersion = DoFullRefresh(appManifest, out applicationCloseRequired); } if (!applicationCloseRequired && EnumUtils.IsFlagSet(updateAction, UpdateAction.VersionUpdate)) { currentVersion = DoVersionUpdate(appManifest, currentVersion, out applicationCloseRequired); } } } catch (Exception e) { resultException = e; LOG.Error("ThreadWorkProc: Failed to run thread", e); } _isRunning = false; DoCompleteCallback(updateAction, currentVersion, applicationCloseRequired, resultException); }
protected UpdateApplicationManifest GetApplicationManifest() { LOG.Debug("GetApplicationManifest: Attempting to download application manifest"); string statusString = "Retrieving update manifest file from server, please wait ..."; DoStatusCallback(-1, statusString); byte[] manifestData = DownloadData(_manifestDownloadUrl, delegate(int percentComplete, object callbackParam) { DoStatusCallback(percentComplete, callbackParam.ToString()); return(!_cancelUpdate); }, statusString ); LOG.Debug("GetApplicationManifest: Attempting to deserialize application manifest"); UpdateApplicationManifest appManifest = _serializationUtils.Deserialize <UpdateApplicationManifest>(manifestData); appManifest.CurrentDatabaseVersion = VersionFromString(appManifest.CurrentDatabaseVersionStr); appManifest.LastFullUpdateVersion = VersionFromString(appManifest.LastFullUpdateVersionStr); appManifest.CurrentApplicationVersion = VersionFromString(appManifest.CurrentApplicationVersionStr); if ((appManifest.CurrentDatabaseVersion != null) || (appManifest.LastFullUpdateVersion != null)) { if ((appManifest.CurrentDatabaseVersion == null) || (appManifest.LastFullUpdateVersion == null)) { throw new InvalidDataException("Manifest file contains a unspecified database versions"); } if (appManifest.CurrentDatabaseVersion < appManifest.LastFullUpdateVersion) { throw new InvalidDataException(string.Format("Manifest file contains a current database version that is less than the last full update version: CurrentDatabaseVersion({0}) and LastFullUpdateVersion({1})", appManifest.CurrentDatabaseVersion.ToString(), appManifest.LastFullUpdateVersion.ToString())); } if (string.IsNullOrEmpty(appManifest.DatabaseFileDownloadUrl)) { throw new InvalidDataException("Manifest file does not contain DatabaseFileDownloadUrl"); } if (string.IsNullOrEmpty(appManifest.DatabaseScriptsDownloadUrl)) { throw new InvalidDataException("Manifest file does not contain DatabaseScriptsDownloadUrl"); } } if (appManifest.CurrentApplicationVersion != null) { if (string.IsNullOrEmpty(appManifest.ApplicationDownloadUrl)) { throw new InvalidDataException("Manifest file does not contain ApplicationDownloadUrl"); } } LOG.Debug("GetApplicationManifest: Got application manifest: CurrentDatabaseVersion({0}) and LastFullUpdateVersion({1}) and CurrentApplicationVersion({2})", (appManifest.CurrentDatabaseVersion == null) ? "Unspecified" : appManifest.CurrentDatabaseVersion.ToString(), (appManifest.LastFullUpdateVersion == null) ? "Unspecified" : appManifest.LastFullUpdateVersion.ToString(), (appManifest.CurrentApplicationVersion == null) ? "Unspecified" : appManifest.CurrentApplicationVersion.ToString()); return(appManifest); }
protected override Version DoFullRefresh(UpdateApplicationManifest appManifest, out bool applicationCloseRequired) { string programParentPath = Path.GetDirectoryName(_programExeFilePath); if (!FileUtils.IsWritableDirectory(programParentPath)) { LOG.Debug("DoFullRefresh: Cannot write to folder: {0}", programParentPath); throw new UnauthorizedAccessException(string.Format("Cannot write to directory \"{0}\"", programParentPath)); } LOG.Debug("DoFullRefresh: Attempting to download updater file"); string tempUpdaterFilePath = MakeTempFilePath(); string statusString = string.Format("Downloading updater content for version {0}.{1}.{2} ...", appManifest.CurrentApplicationVersion.Major.ToString(), appManifest.CurrentApplicationVersion.Minor.ToString(), appManifest.CurrentApplicationVersion.Build.ToString()); DoStatusCallback(0, statusString); DownloadFile(appManifest.ApplicationDownloadUrl, tempUpdaterFilePath, delegate(int percentComplete, object callbackParam) { DoStatusCallback(percentComplete, callbackParam.ToString()); return(!_cancelUpdate); }, statusString); try { CheckToCancel(); DoStatusCallback(-1, "Launching updater application ..."); tempUpdaterFilePath = FileUtils.ChangeFileExtension(tempUpdaterFilePath, ".exe"); CheckToCancel(); ProcessStartInfo info = new ProcessStartInfo(tempUpdaterFilePath); info.UseShellExecute = true; using (Process process = Process.Start(info)) { } applicationCloseRequired = true; } catch (Exception) { FileUtils.SafeDeleteFile(tempUpdaterFilePath); throw; } return(appManifest.CurrentApplicationVersion); }
protected override Version DoVersionUpdate(UpdateApplicationManifest appManifest, Version existingVersion, out bool applicationCloseRequired) { applicationCloseRequired = false; string statusString = string.Format("Downloading database script updates for version {0} ...", appManifest.CurrentDatabaseVersion.ToString()); DoStatusCallback(0, statusString); string scriptsDirectory = DownloadAllTempFiles(appManifest.DatabaseScriptsDownloadUrl, delegate(int percentComplete, object callbackParam) { DoStatusCallback(percentComplete, callbackParam.ToString()); return(!_cancelUpdate); }, statusString); try { DoStatusCallback(-1, "Performing database script updates ..."); CheckToCancel(); List <string> sortedScriptList = GetSortedScriptList(appManifest, scriptsDirectory, existingVersion); int i = 0; foreach (string scriptFile in sortedScriptList) { Version fromVersion, toVersion; GetVersionsFromScriptFileName(Path.GetFileName(scriptFile), out fromVersion, out toVersion); int percentageComplete = (i++ *100) / sortedScriptList.Count; DoStatusCallback(percentageComplete, "Updating database version {0} to version {1} ...", fromVersion.ToString(), toVersion.ToString()); ExecuteSqlCommandFileAndDelete(scriptFile, _connectionString, true, 3); CheckToCancel(); } DoStatusCallback(100, "Performed database version updates"); Version currentDatabaseVersion = GetDatabaseVersion(_connectionString); if (currentDatabaseVersion != appManifest.CurrentDatabaseVersion) { throw new InvalidDataException(string.Format("Version mismatch during database update: {0} vs. {1}", currentDatabaseVersion.ToString(), appManifest.CurrentDatabaseVersion.ToString())); } } finally { FileUtils.SafeDeleteDirectory(scriptsDirectory); } return(appManifest.CurrentDatabaseVersion); }
protected override Version DoFullRefresh(UpdateApplicationManifest appManifest, out bool applicationCloseRequired) { applicationCloseRequired = false; LOG.Debug("DoFullRefresh: Attempting to download database script file"); string tempSqlFilePath = MakeTempFilePath(".sql"); string statusString = string.Format("Downloading database content for version {0} ...", appManifest.LastFullUpdateVersion.ToString()); DoStatusCallback(0, statusString); DownloadFile(appManifest.DatabaseFileDownloadUrl, tempSqlFilePath, delegate(int percentComplete, object callbackParam) { DoStatusCallback(percentComplete, callbackParam.ToString()); return(!_cancelUpdate); }, statusString); CheckToCancel(); DoStatusCallback(-1, "Performing database full refresh to version {0} (please be patient) ...", appManifest.LastFullUpdateVersion.ToString()); if (DatabaseExists(_connectionString)) { LOG.Debug("DoFullRefresh: Attempting to drop existing database for full refresh"); DropDatabase(_connectionString); } LOG.Debug("DoFullRefresh: Attempting to create database for full refresh"); CreateDatabase(_connectionString); LOG.Debug("DoFullRefresh: Attempting to run database script to populate database for full refresh"); ExecuteSqlCommandFileAndDelete(tempSqlFilePath, _connectionString, true, 0); Version currentDatabaseVersion = GetDatabaseVersion(_connectionString); if (currentDatabaseVersion != appManifest.LastFullUpdateVersion) { throw new InvalidDataException(string.Format("Version mismatch during database full refresh: {0} vs. {1}", currentDatabaseVersion.ToString(), appManifest.LastFullUpdateVersion.ToString())); } return(appManifest.LastFullUpdateVersion); }
protected override UpdateAction GetUpdateAction(UpdateApplicationManifest appManifest, out Version existingVersion) { existingVersion = null; //appManifest.CurrentApplicationVersion = new Version("1.0.18"); if (appManifest.CurrentApplicationVersion != null) { Version exeVersion = VersionFromFile(_programExeFilePath); if (exeVersion < appManifest.CurrentApplicationVersion) { return(UpdateAction.FullRefresh); } } return(UpdateAction.None); }
protected override UpdateAction GetUpdateAction(UpdateApplicationManifest appManifest, out Version existingVersion) { existingVersion = null; if (appManifest.CurrentDatabaseVersion != null) { if (DatabaseExists(_connectionString)) { try { existingVersion = GetDatabaseVersion(_connectionString); } catch (Exception) { } } if (existingVersion == null) { UpdateAction action = UpdateAction.FullRefresh; if (appManifest.CurrentDatabaseVersion > appManifest.LastFullUpdateVersion) { action |= UpdateAction.VersionUpdate; } return(action); } if (appManifest.CurrentDatabaseVersion > existingVersion) { UpdateAction action = UpdateAction.None; if (appManifest.LastFullUpdateVersion > existingVersion) { action |= UpdateAction.FullRefresh; } if (appManifest.CurrentDatabaseVersion > appManifest.LastFullUpdateVersion) { action |= UpdateAction.VersionUpdate; } return(action); } } return(UpdateAction.None); }
protected abstract Version DoVersionUpdate(UpdateApplicationManifest appManifest, Version existingVersion, out bool applicationCloseRequired);
protected abstract Version DoFullRefresh(UpdateApplicationManifest appManifest, out bool applicationCloseRequired);
protected abstract UpdateAction GetUpdateAction(UpdateApplicationManifest appManifest, out Version existingVersion);
protected override Version DoVersionUpdate(UpdateApplicationManifest appManifest, Version existingVersion, out bool applicationCloseRequired) { throw new NotImplementedException("DoVersionUpdate"); }
private List <string> GetSortedScriptList(UpdateApplicationManifest appManifest, string scriptsDirectory, Version existingDatabaseVersion) { LOG.Debug("GetSortedScriptList: Attempting to find valid script files for update"); List <string> sortedList = new List <string>(Directory.GetFiles(scriptsDirectory, "Update_*.sql", SearchOption.TopDirectoryOnly)); if (sortedList.Count == 0) { throw new InvalidDataException("The script update file did not contain any valid scripts"); } sortedList.Sort(); LOG.Debug("GetSortedScriptList: Extracted {0} script files from downloaded file", sortedList.Count); // We want to return just the list of updates to apply, so find the indexes of those files // Locate initial update script file string searchString = string.Format("UPDATE_{0}_{1}_{2}_TO_", existingDatabaseVersion.Major.ToString("D2"), existingDatabaseVersion.Minor.ToString("D2"), existingDatabaseVersion.Build.ToString("D2")); int startIndex = 0; foreach (string filePath in sortedList) { string fileName = Path.GetFileName(filePath).ToUpper(); if (fileName.StartsWith(searchString)) { break; } ++startIndex; } if (startIndex == sortedList.Count) { throw new InvalidDataException("The script update file did not contain a valid script to update from database version " + existingDatabaseVersion.ToString()); } // Locate last update file searchString = string.Format("_TO_{0}_{1}_{2}.SQL", appManifest.CurrentDatabaseVersion.Major.ToString("D2"), appManifest.CurrentDatabaseVersion.Minor.ToString("D2"), appManifest.CurrentDatabaseVersion.Build.ToString("D2")); int endIndex; for (endIndex = sortedList.Count - 1; endIndex >= 0; endIndex--) { string fileName = Path.GetFileName(sortedList[endIndex]).ToUpper(); if (fileName.EndsWith(searchString)) { break; } } if ((endIndex < 0) || (startIndex > endIndex)) { throw new InvalidDataException("The script update file did not contain a valid script to update to database version " + appManifest.CurrentDatabaseVersion.ToString()); } if (endIndex < (sortedList.Count - 1)) { sortedList.RemoveRange(endIndex + 1, sortedList.Count - endIndex - 1); } if (startIndex > 0) { sortedList.RemoveRange(0, startIndex); } LOG.Debug("GetSortedScriptList: Found {0} script file(s), starting with {1} and ending with {2}", sortedList.Count, Path.GetFileName(sortedList[0]), Path.GetFileName(sortedList[sortedList.Count - 1])); return(sortedList); }