diff --git a/BlazamSetup/BlazamSetup.csproj b/BlazamSetup/BlazamSetup.csproj index d383639..b376eee 100644 --- a/BlazamSetup/BlazamSetup.csproj +++ b/BlazamSetup/BlazamSetup.csproj @@ -438,6 +438,12 @@ PostInstallation.xaml + + Update.xaml + + + WelcomeUpdate.xaml + Repair.xaml @@ -538,6 +544,14 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + Designer MSBuild:Compile diff --git a/BlazamSetup/Data/DatabaseConfiguration.cs b/BlazamSetup/Data/DatabaseConfiguration.cs index 4ade366..f7ce9d6 100644 --- a/BlazamSetup/Data/DatabaseConfiguration.cs +++ b/BlazamSetup/Data/DatabaseConfiguration.cs @@ -9,7 +9,10 @@ public class DatabaseConfiguration public int Port { get; set; } public string Database { get; set; } public string Username { get; set; } - public string Password { get; set; } + public string Password { + get; + set; + } public string ValidationMessage { get diff --git a/BlazamSetup/Data/InstallationConfiguraion.cs b/BlazamSetup/Data/InstallationConfiguraion.cs index 4b1847e..5cb1d55 100644 --- a/BlazamSetup/Data/InstallationConfiguraion.cs +++ b/BlazamSetup/Data/InstallationConfiguraion.cs @@ -20,7 +20,7 @@ internal static class InstallationConfiguraion /// /// This value identifies the version of the installer that was used, it should change every update. /// - internal static string UpdateGuid => "a146351b-8ff5-457e-9aac-c6604a21bd1b".ToUpper(); + internal static string UpdateGuid => "410dd7f9-001d-4916-a991-5ca86987b709".ToUpper(); internal static ProductInformation ProductInformation { get; set; } = new ProductInformation(); @@ -39,9 +39,9 @@ internal static string InstallDirPath { get => installDirPath; set { - installDirPath = value; - ProductInformation.InstallLocation = Path.GetFullPath(value+"\\Blazam"); - ProductInformation.UninstallString = '"'+Path.GetFullPath(value+"\\Blazam\\setup.exe")+"\" /u"; + installDirPath = Path.GetFullPath(value + "\\"); + ProductInformation.InstallLocation = Path.GetFullPath(value+"\\"); + ProductInformation.UninstallString = '"'+Path.GetFullPath(value+"\\setup.exe")+"\" /u"; } } internal static DatabaseConfiguration DatabaseConfiguration { get; set; } = new DatabaseConfiguration(); diff --git a/BlazamSetup/Data/ProductInformation.cs b/BlazamSetup/Data/ProductInformation.cs index 8575ecf..064977e 100644 --- a/BlazamSetup/Data/ProductInformation.cs +++ b/BlazamSetup/Data/ProductInformation.cs @@ -13,7 +13,7 @@ internal class ProductInformation { public string DisplayName { get; set; } = "Blazam"; public string Publisher { get; set; } = "blazam.org"; - public string DisplayVersion { get; set; } = "0.8"; + public string DisplayVersion { get; set; } = "1.0"; public string Comments { get; set; } = " A web based Active Directry management portal"; public int NoRepair { get; set; } = 0; public int NoModify { get; set; } = 1; diff --git a/BlazamSetup/MainWindow.xaml.cs b/BlazamSetup/MainWindow.xaml.cs index b54e5c5..a8b9218 100644 --- a/BlazamSetup/MainWindow.xaml.cs +++ b/BlazamSetup/MainWindow.xaml.cs @@ -11,13 +11,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; using System.Windows.Threading; namespace BlazamSetup @@ -43,8 +37,8 @@ public MainWindow() if (RegistryService.InstallationExists) { InstallationConfiguraion.ProductInformation = RegistryService.GetProductInformation(); - - InstallationConfiguraion.InstalledVersion = FileSystemService.GetFileVersion(InstallationConfiguraion.ProductInformation.InstallLocation); + InstallationConfiguraion.InstallDirPath = RegistryService.InstallLocation; + InstallationConfiguraion.InstalledVersion = FileSystemService.GetFileVersion(InstallationConfiguraion.ProductInformation.InstallLocation+"\\Blazam.exe"); } if (App.StartupArgs.Args.Any(arg => arg.StartsWith("/u"))) { diff --git a/BlazamSetup/Services/AppSettingsService.cs b/BlazamSetup/Services/AppSettingsService.cs index bd438fc..4af45ca 100644 --- a/BlazamSetup/Services/AppSettingsService.cs +++ b/BlazamSetup/Services/AppSettingsService.cs @@ -19,7 +19,7 @@ internal static class AppSettingsService public static bool Configure() { - string path = Path.GetFullPath(InstallationConfiguraion.InstallDirPath + @"\\Blazam\\"); + string path = Path.GetFullPath(InstallationConfiguraion.InstallDirPath); string jsonString = System.IO.File.ReadAllText(path+"appsettings.json"); @@ -46,8 +46,8 @@ public static bool Configure() internal static void Copy() { - string exampleFilePath = InstallationConfiguraion.InstallDirPath + "\\Blazam\\appsettings.example.json"; - string filePath = InstallationConfiguraion.InstallDirPath + "\\Blazam\\appsettings.json"; + string exampleFilePath = Path.GetFullPath(InstallationConfiguraion.InstallDirPath + "\\appsettings.example.json"); + string filePath = Path.GetFullPath(InstallationConfiguraion.InstallDirPath + "\\appsettings.json"); if (File.Exists(exampleFilePath)) File.Copy(exampleFilePath, filePath,true); diff --git a/BlazamSetup/Services/DownloadService.cs b/BlazamSetup/Services/DownloadService.cs index b54f931..1cbcdc4 100644 --- a/BlazamSetup/Services/DownloadService.cs +++ b/BlazamSetup/Services/DownloadService.cs @@ -19,14 +19,14 @@ internal static class DownloadService public static string SetupTempDirectory = Path.GetTempPath() + "BlazamSetup\\"; public static string SourceDirectory = Path.GetTempPath() + "BlazamSetup\\setup\\"; public static string UpdateFile = SetupTempDirectory + "blazam.zip"; - private static ReleaseAsset latestRelease; + public static ReleaseAsset LatestRelease; public static int ExpectedSize { get; private set; } public static CancellationTokenSource cancellationTokenSource { get; private set; } = new CancellationTokenSource(); public static int CompletedBytes { get; private set; } public static InstallEvent DownloadPercentageChanged { get; set; } - public static async Task Download() + public static async Task Download(string version=null) { Log.Information("Download started"); @@ -34,91 +34,99 @@ public static async Task Download() - var branch = "stable"; + var branch = "Release"; //Get the releases from the repo var releases = await githubclient.Repository.Release.GetAll("Blazam-App", "Blazam"); //Filter the releases to the selected branch - var branchReleases = releases.Where(r => r.TagName.ToLower().Contains(branch)); + var branchReleases = releases.Where(r => r.TagName.ToLower().Contains(branch)|| r.TagName.ToLower().Contains("stable")); //Get the first release,which should be the most recent - latestRelease = branchReleases.FirstOrDefault()?.Assets.FirstOrDefault(); + LatestRelease = branchReleases.FirstOrDefault()?.Assets.FirstOrDefault(); //Get the release filename to prepare a version object - var filename = Path.GetFileNameWithoutExtension(latestRelease.Name); + var filename = Path.GetFileNameWithoutExtension(LatestRelease.Name); //Create that version object if (filename == null) throw new ApplicationUpdateException("Filename could not be retrieved from GitHub"); + if (version != null) + { + var matchingRelease = releases.Where(r=>r.TagName.ToLower().Contains(version)).FirstOrDefault(); + if(matchingRelease != null) + { + return await DownloadAsset(matchingRelease.Assets.FirstOrDefault()); - if (latestRelease != null) + } + throw new ApplicationUpdateException("Could not find requested version number. Try running an update."); + } + else if (LatestRelease != null) { + return await DownloadAsset(LatestRelease); + } + return false; + } - using (var client = new HttpClient()) + private static async Task DownloadAsset(ReleaseAsset releaseToDownload) + { + using (var client = new HttpClient()) + { + using (var response = await client.GetAsync(releaseToDownload.BrowserDownloadUrl, HttpCompletionOption.ResponseHeadersRead)) { - using (var response = await client.GetAsync(latestRelease.BrowserDownloadUrl, HttpCompletionOption.ResponseHeadersRead)) + if (!response.IsSuccessStatusCode) { - if (!response.IsSuccessStatusCode) - { - //Loggers.UpdateLogger?.Debug("Unable to connect to download url: " + response.StatusCode + " : " + response.ReasonPhrase); + //Loggers.UpdateLogger?.Debug("Unable to connect to download url: " + response.StatusCode + " : " + response.ReasonPhrase); - return false; - } + return false; + } - if (File.Exists(UpdateFile)) - { - if (Debugger.IsAttached) - { - return true; - } - else - { - File.Delete(UpdateFile); - } + if (File.Exists(UpdateFile)) + { + + File.Delete(UpdateFile); + - } - using (var streamToReadFrom = await response.Content.ReadAsStreamAsync()) + } + using (var streamToReadFrom = await response.Content.ReadAsStreamAsync()) + { + Directory.CreateDirectory(SetupTempDirectory); + File.Create(UpdateFile).Close(); + using (var streamToWriteTo = File.OpenWrite(UpdateFile)) { - Directory.CreateDirectory(SetupTempDirectory); - File.Create(UpdateFile).Close(); - using (var streamToWriteTo = File.OpenWrite(UpdateFile)) - { - ExpectedSize = (int)latestRelease.Size; - var buffer = new byte[262144]; - //var buffer = new byte[4096]; - int bytesRead; - int totalBytesRead = 0; + ExpectedSize = (int)releaseToDownload.Size; + var buffer = new byte[262144]; + //var buffer = new byte[4096]; + int bytesRead; + int totalBytesRead = 0; - while ((bytesRead = await streamToReadFrom.ReadAsync(buffer, 0, buffer.Length)) > 0) + while ((bytesRead = await streamToReadFrom.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + if (!cancellationTokenSource.IsCancellationRequested) + { + await streamToWriteTo.WriteAsync(buffer, 0, bytesRead); + totalBytesRead += bytesRead; + CompletedBytes = totalBytesRead; + var percentage = (CompletedBytes / (double)ExpectedSize * 100); + DownloadPercentageChanged?.Invoke((int)percentage); + } + else { - if (!cancellationTokenSource.IsCancellationRequested) - { - await streamToWriteTo.WriteAsync(buffer, 0, bytesRead); - totalBytesRead += bytesRead; - CompletedBytes = totalBytesRead; - var percentage = (CompletedBytes / (double)ExpectedSize * 100); - DownloadPercentageChanged?.Invoke((int)percentage); - } - else - { - streamToReadFrom.Close(); - DownloadPercentageChanged?.Invoke(0); - - return false; - } + streamToReadFrom.Close(); + DownloadPercentageChanged?.Invoke(0); + + return false; } + } - return true; + return true; - } } } } - } - return false; } + public static void CleanDownload() { @@ -180,18 +188,21 @@ internal static async Task UnpackDownload() Log.Information("Extracting files: " + SourceDirectory); CleanSource(); + Directory.CreateDirectory(SourceDirectory); ZipArchive download = new ZipArchive(File.OpenRead(UpdateFile)); download.ExtractToDirectory(SourceDirectory); download.Dispose(); File.Delete(UpdateFile); return true; + } catch (Exception ex) { Log.Error("Error unpacking download: {@Error}", ex); } + return false; }); diff --git a/BlazamSetup/Services/FileSystemService.cs b/BlazamSetup/Services/FileSystemService.cs index 8e90698..3d7c136 100644 --- a/BlazamSetup/Services/FileSystemService.cs +++ b/BlazamSetup/Services/FileSystemService.cs @@ -95,7 +95,9 @@ internal static string GetFileVersion(string installLocation) { if (File.Exists(installLocation)) { - return FileVersionInfo.GetVersionInfo(installLocation).ProductVersion; + var fvi = FileVersionInfo.GetVersionInfo(installLocation); + string version = fvi.FileVersion+"."+fvi.ProductVersion; + return version; } diff --git a/BlazamSetup/Services/IISManageer.cs b/BlazamSetup/Services/IISManageer.cs index ac56785..b7ac658 100644 --- a/BlazamSetup/Services/IISManageer.cs +++ b/BlazamSetup/Services/IISManageer.cs @@ -26,7 +26,7 @@ public static bool CreateApplication() site = serverManager.Sites.Add("Blazam", "http", httpBinding, - Path.GetFullPath(InstallationConfiguraion.InstallDirPath + @"\\Blazam\\")); + Path.GetFullPath(InstallationConfiguraion.InstallDirPath)); } Log.Information("IIS Site {@Site}", site); @@ -34,7 +34,7 @@ public static bool CreateApplication() serverManager.CommitChanges(); FileSystemService.AddPermission( - Path.GetFullPath(InstallationConfiguraion.InstallDirPath + "\\Blazam\\"), + Path.GetFullPath(InstallationConfiguraion.InstallDirPath), "IIS_IUSRS", FileSystemRights.ReadAndExecute ); diff --git a/BlazamSetup/Services/InstallationService.cs b/BlazamSetup/Services/InstallationService.cs index 450fe8c..7d93224 100644 --- a/BlazamSetup/Services/InstallationService.cs +++ b/BlazamSetup/Services/InstallationService.cs @@ -21,11 +21,11 @@ internal static class InstallationService internal static async Task StartInstallationAsync() { - Log.Information("Installattion Started {@InstallationType} {@InstallDirPath} {@DatabaseConfiguration}", InstallationConfiguraion.InstallationType, InstallationConfiguraion.InstallDirPath, InstallationConfiguraion.DatabaseConfiguration); + Log.Information("Installation Started {@InstallationType} {@InstallDirPath} {@DatabaseConfiguration}", InstallationConfiguraion.InstallationType, InstallationConfiguraion.InstallDirPath, InstallationConfiguraion.DatabaseConfiguration); if (!await PreInstallation()) Rollback(); if (CancellationTokenSource.IsCancellationRequested) return; - if (!await ApplyProgramFilesAsync(InstallationConfiguraion.InstallDirPath + "\\Blazam\\")) Rollback(); + if (!await ApplyProgramFilesAsync(InstallationConfiguraion.InstallDirPath)) Rollback(); if (CancellationTokenSource.IsCancellationRequested) return; await Task.Run(() => @@ -36,7 +36,7 @@ await Task.Run(() => if (!CreateProgramDataDirectory()) Rollback(); if (CancellationTokenSource.IsCancellationRequested) return; - + if (InstallationConfiguraion.InstallationType == InstallType.Service) { OnStepTitleChanged?.Invoke("Install Services"); @@ -69,7 +69,7 @@ await Task.Run(() => string identity = "IIS_IUSRS"; if (InstallationConfiguraion.InstallationType == InstallType.Service) identity = "Network Service"; - + Directory.CreateDirectory(InstallationConfiguraion.DatabaseConfiguration.SqliteDirectory); FileSystemService.AddPermission(InstallationConfiguraion.DatabaseConfiguration.SqliteDirectory, identity, @@ -77,14 +77,13 @@ await Task.Run(() => ); } AppSettingsService.Configure(); - InstallationConfiguraion.ProductInformation.EstimatedSize = (int)(FileSystemService.GetDirectorySize(InstallationConfiguraion.ProductInformation.InstallLocation)/1024); + InstallationConfiguraion.ProductInformation.EstimatedSize = (int)(FileSystemService.GetDirectorySize(InstallationConfiguraion.ProductInformation.InstallLocation) / 1024); RegistryService.SetProductInformation(InstallationConfiguraion.ProductInformation); OnProgress?.Invoke(100); OnStepTitleChanged?.Invoke("Installation Finished"); Log.Information("Installation Finished Successfully"); MainWindow.DisableBack(); - MainWindow.EnableNext(); OnInstallationFinished?.Invoke(); }); } @@ -109,7 +108,8 @@ private static bool CreateProgramDataDirectory() FileSystemRights.Write | FileSystemRights.Modify | FileSystemRights.ReadAndExecute ); return true; - }catch (Exception ex) + } + catch (Exception ex) { Log.Error("Error creating program data directory: {@Error}", ex); @@ -221,67 +221,47 @@ internal static void Cancel() CancellationTokenSource.Cancel(); } } + internal static async Task StartUpdateAsync() + { + + + var targetDirectory = InstallationConfiguraion.InstallDirPath; + OnStepTitleChanged("Downloading latest version..."); + DownloadService.DownloadPercentageChanged = ((val) => { OnProgress(val); }); + if (!await DownloadService.Download()) return false; + OnProgress(0); + if (DownloadService.LatestRelease.Name.Contains(InstallationConfiguraion.InstalledVersion)) + throw new ApplicationUpdateException("Latest version is already installed."); + OnStepTitleChanged("Preparing update..."); + + if (!await PreInstallation()) return false; + if (CancellationTokenSource.IsCancellationRequested) return false; + OnStepTitleChanged("Applying update..."); + //InstallationService.OnProgress= ((val) => { OnProgress(val); }); + // InstallationService.OnInstallationFinished= (() => { OnInstallationFinished(); }); + if (!await ApplyProgramFilesAsync(InstallationConfiguraion.InstallDirPath)) return false; + if (CancellationTokenSource.IsCancellationRequested) return false; + + OnInstallationFinished?.Invoke(); + return true; + } internal static async Task StartReparAsync() { - return await Task.Run(() => - { - try - { - - var targetDirectory = InstallationConfiguraion.InstallDirPath; - OnStepTitleChanged?.Invoke("Repairing Files"); - Log.Information("Repair File copy started"); - bool copyingDownTree = false; - if (targetDirectory.Contains(DownloadService.SourceDirectory)) - { - copyingDownTree = true; - } - var totalFiles = FileSystemService.GetFileCount(DownloadService.SourceDirectory); - var fileIndex = 0; - if (Directory.Exists(DownloadService.SetupTempDirectory)) - { - var directories = Directory.GetDirectories(DownloadService.SourceDirectory, "*", SearchOption.AllDirectories).AsEnumerable(); - - if (copyingDownTree) - directories = directories.Where(d => !d.Contains(targetDirectory)); - - //Now Create all of the directories - foreach (string dirPath in directories) - { - Log.Information("Creating directory: " + dirPath); - - Directory.CreateDirectory(dirPath.Replace(DownloadService.SourceDirectory, targetDirectory)); - } - var files = Directory.GetFiles(DownloadService.SourceDirectory, "*.*", SearchOption.AllDirectories).AsEnumerable(); - - if (copyingDownTree) - files = files.Where(f => !f.Contains(targetDirectory)); - //Copy all the files & Replaces any files with the same name - foreach (string path in files) - { - var newPath = path.Replace(DownloadService.SourceDirectory, targetDirectory); - Log.Information("Copying file: " + newPath); - - File.Copy(path, newPath, true); - fileIndex++; - OnProgress?.Invoke((fileIndex / totalFiles) * 100); - } - CopySetup(targetDirectory); - return true; - } - } - catch (Exception ex) - { - Log.Error("Error Copying files {@Error}", ex); + var targetDirectory = InstallationConfiguraion.InstallDirPath; + OnStepTitleChanged("Downloading current version..."); + DownloadService.DownloadPercentageChanged = ((val) => { OnProgress(val); }); + if (!await DownloadService.Download(InstallationConfiguraion.InstalledVersion)) return false; + if (!await PreInstallation()) return false; + if (CancellationTokenSource.IsCancellationRequested) return false; + if (!await ApplyProgramFilesAsync(InstallationConfiguraion.InstallDirPath)) return false; + if (CancellationTokenSource.IsCancellationRequested) return false; + OnInstallationFinished?.Invoke(); - Console.WriteLine(ex.Message); - } - return false; - }); + return true; } private static bool RemoveProgramFiles(string installPath) diff --git a/BlazamSetup/Services/PrerequisiteChecker.cs b/BlazamSetup/Services/PrerequisiteChecker.cs index 3665d78..9ba4d6d 100644 --- a/BlazamSetup/Services/PrerequisiteChecker.cs +++ b/BlazamSetup/Services/PrerequisiteChecker.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Management; +using System.Reflection; using System.Text; using System.Threading.Tasks; using static System.Net.Mime.MediaTypeNames; @@ -57,5 +59,21 @@ internal static bool CheckForAspCoreHosting() return false; } + internal static bool CheckForWebSockets() + { + ManagementClass objMC = new ManagementClass("Win32_OptionalFeature"); + ManagementObjectCollection objMOC = objMC.GetInstances(); + foreach (ManagementObject objMO in objMOC) + { + string featureName = (string)objMO.Properties["Name"].Value; + if (featureName.Equals("IIS-WebSockets", StringComparison.InvariantCultureIgnoreCase)) + { + var path = (uint)objMO.Properties["InstallState"].Value; + return path.Equals(1); + } + + } + return false; + } } } diff --git a/BlazamSetup/Services/RegistryService.cs b/BlazamSetup/Services/RegistryService.cs index 5fedb1e..2c17e5a 100644 --- a/BlazamSetup/Services/RegistryService.cs +++ b/BlazamSetup/Services/RegistryService.cs @@ -86,6 +86,27 @@ public static bool InstallationExists } } } + public static string InstallLocation + { + get + { + try + { + var key = OpenKey(); + if (key == null) return null; + var installLocation = key.GetValue("InstallLocation"); + if (installLocation is string installLocationString && !installLocationString.IsNullOrEmpty()) + { + return installLocationString; + } + return null; + } + catch (Exception e) + { + return null; + } + } + } public static bool CreateUninstallKey() { try diff --git a/BlazamSetup/Services/ServiceManager.cs b/BlazamSetup/Services/ServiceManager.cs index 4db70bb..365b183 100644 --- a/BlazamSetup/Services/ServiceManager.cs +++ b/BlazamSetup/Services/ServiceManager.cs @@ -49,9 +49,9 @@ internal static bool Install() if (!IsInstalled) { CreateTempNSSM(); - var path = InstallationConfiguraion.InstallDirPath + "\\Blazam\\nssm.exe"; + var path = InstallationConfiguraion.InstallDirPath + "\\nssm.exe"; - var arguments = "install " + ServiceName + " \"" + InstallationConfiguraion.InstallDirPath + "\\Blazam\\blazam.exe\""; + var arguments = "install " + ServiceName + " \"" + InstallationConfiguraion.InstallDirPath + "\\blazam.exe\""; Process.Start(path, arguments).WaitForExit(); arguments = "set " + ServiceName + " ObjectName \"NT AUTHORITY\\Network Service\" \"\""; Process.Start(path, arguments).WaitForExit(); diff --git a/BlazamSetup/Steps/ConfigureDatabaseConnection.xaml b/BlazamSetup/Steps/ConfigureDatabaseConnection.xaml index 59a2654..bfb8183 100644 --- a/BlazamSetup/Steps/ConfigureDatabaseConnection.xaml +++ b/BlazamSetup/Steps/ConfigureDatabaseConnection.xaml @@ -12,30 +12,30 @@ -