Files
Pilz.Updating/Pilz.Updating.UpdateInstaller.Lib/UpdateInstaller.cs
2023-11-21 08:55:48 +01:00

173 lines
6.1 KiB
C#

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);
}
}
}