using System; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Microsoft.VisualBasic.CompilerServices; namespace Pilz.Updating.UpdateInstaller.Lib { public class UpdateInstaller { // E v e n t s public delegate void UpdateInstallerEventHandler(object sender, UpdateInstallerEventArgs e); public delegate void UpdateInstallerStepEventHandler(object sender, UpdateInstallerStepEventArgs e); public delegate void StatusChangesEventHandler(object sender, UpdateInstallerStatusChangedEventArgs e); public event StatusChangesEventHandler StatusChanges; public event UpdateInstallerStepEventHandler OnStep; // F i e l d s private string dataPath = string.Empty; // P r o p e r t i e s public UpdateInstallerConfig Configuration { get; private set; } // C o n s t r c u t o r s public UpdateInstaller(UpdateInstallerConfig config) { Configuration = config; } // F e a t u r e s private void ChangeStep(UpdateInstallerStep step, UpdateInstallerStepState state) { OnStep?.Invoke(this, new UpdateInstallerStepEventArgs(this, step, state)); } private void ChangeStatus(UpdateInstallerStatus newStatus) { StatusChanges?.Invoke(this, new UpdateInstallerStatusChangedEventArgs(newStatus)); } public void StartHostApplication() { if (!string.IsNullOrEmpty(Conversions.ToString(Configuration.RestartHostApplication)) && File.Exists(Configuration.HostApplicationProcessPath)) { Process.Start(Configuration.HostApplicationProcessPath, Configuration.RestartHostApplicationArguments); } } public void InstallUpdate() { ChangeStep(UpdateInstallerStep.Startup, UpdateInstallerStepState.Default); // Extract Package ChangeStatus(UpdateInstallerStatus.Extracting); ChangeStep(UpdateInstallerStep.ExtractPackage, UpdateInstallerStepState.PreEvent); ExtractPackage(); ChangeStep(UpdateInstallerStep.ExtractPackage, UpdateInstallerStepState.PostEvent); // Install Package ChangeStatus(UpdateInstallerStatus.CopyingFiles); ChangeStep(UpdateInstallerStep.CopyFiles, UpdateInstallerStepState.PreEvent); CopyFiles(); ChangeStep(UpdateInstallerStep.CopyFiles, UpdateInstallerStepState.PostEvent); // Delete Package ChangeStatus(UpdateInstallerStatus.RemovingFiles); ChangeStep(UpdateInstallerStep.DeletePackage, UpdateInstallerStepState.PreEvent); DeletePackage(); ChangeStep(UpdateInstallerStep.DeletePackage, UpdateInstallerStepState.PostEvent); // Finish ChangeStatus(UpdateInstallerStatus.Done); ChangeStep(UpdateInstallerStep.Finish, UpdateInstallerStepState.Default); } public void WaitForHostApplication() { bool forcedKill = false; bool enabled = true; var stw = new Stopwatch(); stw.Start(); Process[] getProcesses() => Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Configuration.HostApplicationProcessPath)); while (enabled) { if (getProcesses().Any()) { if (stw.ElapsedMilliseconds >= Configuration.MillisecondsToWaitForHostApplicationToClose) { if (!forcedKill && Configuration.ForceClosingHostApplication) { foreach (Process p in getProcesses()) p.Kill(); stw.Reset(); forcedKill = true; } else { stw.Stop(); enabled = false; } } } else { enabled = false; } } } private void ExtractPackage() { string packagePath = Configuration.PackagePath; string zipPath = Path.Combine(packagePath, PackageFileNameDefinations.ZIP_PACKAGE_FILENAME); dataPath = Path.Combine(packagePath, Path.GetFileNameWithoutExtension(PackageFileNameDefinations.ZIP_PACKAGE_FILENAME)); var dataPathDir = new DirectoryInfo(dataPath); if (dataPathDir.Exists) { dataPathDir.Delete(true); Task.Delay(100); } ZipFile.ExtractToDirectory(zipPath, dataPath); } private void CopyFiles() { var sourceDir = new DirectoryInfo(Path.Combine(dataPath, PackageFileNameDefinations.ZIP_APP_DATA_FILES_DIRECTORY)); var destDir = new DirectoryInfo(Configuration.HostApplicationPath); CopyFiles(sourceDir, destDir); } private void CopyFiles(DirectoryInfo sourceDir, DirectoryInfo destinationDir) { if (!destinationDir.Exists) { destinationDir.Create(); } foreach (FileInfo sFile in sourceDir.EnumerateFiles("*", SearchOption.TopDirectoryOnly)) { var dFile = new FileInfo(Path.Combine(destinationDir.FullName, sFile.Name)); try { sFile.CopyTo(dFile.FullName, true); } catch (Exception) { } } foreach (DirectoryInfo sDir in sourceDir.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)) { var dDir = destinationDir.CreateSubdirectory(sDir.Name); CopyFiles(sDir, dDir); } } private void DeletePackage() { Directory.Delete(Configuration.PackagePath, true); } } }