/// <summary>Starts the installer program, when all presumtions are fullfilled.</summary> /// <param name="isAltaxoCurrentlyStarting">If set to <c>true</c>, Altaxo will be restarted after the installation is done.</param> /// <param name="commandLineArgs">Original command line arguments. Can be <c>null</c> when calling this function on shutdown.</param> /// <returns>True if the installer program was started. Then Altaxo have to be shut down immediately. Returns <c>false</c> if the installer program was not started.</returns> public bool Run(bool isAltaxoCurrentlyStarting, string[] commandLineArgs) { var updateSettings = Current.PropertyService.GetValue(Altaxo.Settings.AutoUpdateSettings.PropertyKeyAutoUpdate, Main.Services.RuntimePropertyKind.UserAndApplicationAndBuiltin, () => new Altaxo.Settings.AutoUpdateSettings()); var installationRequested = (isAltaxoCurrentlyStarting && updateSettings.InstallAtStartup) || (!isAltaxoCurrentlyStarting && updateSettings.InstallAtShutdown); if (!installationRequested) { return(false); } bool loadUnstable = updateSettings.DownloadUnstableVersion; FileStream versionFileStream = null; FileStream packageStream = null; // try to lock the version file in the download directory, thus no other process can modify it try { var downloadFolder = PackageInfo.GetDownloadDirectory(loadUnstable); var versionFileName = Path.Combine(downloadFolder, PackageInfo.VersionFileName); versionFileStream = new FileStream(versionFileName, FileMode.Open, FileAccess.Read, FileShare.Read); var info = PackageInfo.GetPresentDownloadedPackage(versionFileStream, downloadFolder, out packageStream); if (null == info || null == packageStream) { return(false); } var entryAssembly = System.Reflection.Assembly.GetEntryAssembly(); var entryAssemblyVersion = entryAssembly.GetName().Version; if (info.Version <= entryAssemblyVersion) { return(false); // no need to update } if (updateSettings.ConfirmInstallation) { var question = string.Format( "A new Altaxo update is available (from current version {0} to new {1} version {2}).\r\n\r\n" + "If you don't want to have auto updates, please deactivate them by choosing 'Tools'->'Options' menu in Altaxo.\r\n" + "\r\n" + "Do you want to update to {1} version {2} now?", entryAssemblyVersion, PackageInfo.GetStableIdentifier(info.IsUnstableVersion).ToLower(), info.Version); if (false == Current.Gui.YesNoMessageBox(question, "Altaxo update available", true)) { return(false); // user don't want to update } } // copy the Updater executable to the download folder var entryAssemblyFolder = Path.GetDirectoryName(entryAssembly.Location); var installerFullSrcName = Path.Combine(entryAssemblyFolder, UpdateInstallerFileName); var installerFullDestName = Path.Combine(downloadFolder, UpdateInstallerFileName); File.Copy(installerFullSrcName, installerFullDestName, true); // both the version file and the package stream are locked now // so we can start the updater program var eventName = System.Guid.NewGuid().ToString(); var waitForRemoteStartSignal = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.ManualReset, eventName); var processInfo = new System.Diagnostics.ProcessStartInfo { FileName = installerFullDestName }; var stb = new StringBuilder(); stb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "\"{0}\"\t\"{1}\"\t{2}\t{3}\t{4}\t\"{5}\"", eventName, packageStream.Name, updateSettings.ShowInstallationWindow ? 1 : 0, updateSettings.InstallationWindowClosingTime, isAltaxoCurrentlyStarting ? 1 : 0, entryAssembly.Location); if (isAltaxoCurrentlyStarting && commandLineArgs != null && commandLineArgs.Length > 0) { foreach (var s in commandLineArgs) { stb.AppendFormat("\t\"{0}\"", s); } } processInfo.Arguments = stb.ToString(); processInfo.CreateNoWindow = false; processInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal; // Start the updater program var process = System.Diagnostics.Process.Start(processInfo); for (; ;) { // we wait until the update program signals that it has now taken the VersionInfo file if (waitForRemoteStartSignal.WaitOne(100)) { break; } if (process.HasExited) { return(false); // then something has gone wrong or the user has closed the window } } return(true); } catch (Exception) { return(false); } finally { if (null != packageStream) { packageStream.Close(); } if (null != versionFileStream) { versionFileStream.Close(); } } }
/// <summary>Runs the <see cref="Downloader"/>.</summary> /// <remarks> /// The download is done in steps: /// <para>Firstly, the appropriate version file in the application data directory is locked, /// so that no other program can use it, until this program ends.</para> /// <para>Then, the version file is downloaded from the remote location.</para> /// <para>If there is already a valid version file in the download directory, /// and the version obtained from the remote version file is equal to the version obtained from the version file in the download directory, /// then the package was already downloaded before. Then we only check that the package file is also present and that it has the appropriate hash sum.</para> /// <para>Else, if the version obtained from the remote version file is higher than the program's current version, /// we download the package file from the remote location.</para> /// </remarks> public void Run() { if (!Directory.Exists(_storagePath)) { Directory.CreateDirectory(_storagePath); SetDownloadDirectoryAccessRights(_storagePath); } var versionFileFullName = Path.Combine(_storagePath, PackageInfo.VersionFileName); using (var fs = new FileStream(versionFileFullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { fs.Seek(0, SeekOrigin.Begin); var alreadyDownloadedVersion = PackageInfo.GetPresentDownloadedPackage(fs, _storagePath); fs.Seek(0, SeekOrigin.Begin); using (var webClient = new System.Net.WebClient()) { Console.Write("Starting to download version file ..."); var versionData = webClient.DownloadData(_downloadURL + PackageInfo.VersionFileName); Console.WriteLine(" ok! ({0} bytes downloaded)", versionData.Length); // we leave the file open, thus no other process can access it var parsedVersions = PackageInfo.FromStream(new MemoryStream(versionData)); fs.Write(versionData, 0, versionData.Length); fs.Flush(); // write the new version to disc in order to change the write date // from all parsed versions, choose that one that matches the requirements var parsedVersion = PackageInfo.GetHighestVersion(parsedVersions); if (null != parsedVersion) { Console.WriteLine("The remote package version is: {0}", parsedVersion.Version); } else { Console.WriteLine("This computer does not match the requirements of any package. The version file contains {0} packages.", parsedVersions.Length); return; } if (Comparer <Version> .Default.Compare(parsedVersion.Version, _currentVersion) > 0) // if the remote version is higher than the currently installed Altaxo version { Console.Write("Cleaning download directory ..."); CleanDirectory(versionFileFullName); // Clean old downloaded files from the directory Console.WriteLine(" ok!"); var packageUrl = _downloadURL + PackageInfo.GetPackageFileName(parsedVersion.Version); var packageFileName = Path.Combine(_storagePath, PackageInfo.GetPackageFileName(parsedVersion.Version)); Console.WriteLine("Starting download of package file ..."); webClient.DownloadProgressChanged += EhDownloadOfPackageFileProgressChanged; webClient.DownloadFileCompleted += EhDownloadOfPackageFileCompleted; _isDownloadOfPackageCompleted = false; webClient.DownloadFileAsync(new Uri(packageUrl), packageFileName);// download the package asynchronously to get progress messages for (; !_isDownloadOfPackageCompleted;) { System.Threading.Thread.Sleep(250); } webClient.DownloadProgressChanged -= EhDownloadOfPackageFileProgressChanged; webClient.DownloadFileCompleted -= EhDownloadOfPackageFileCompleted; Console.WriteLine("Download finished!"); // make at least the test for the right length var fileInfo = new FileInfo(packageFileName); if (fileInfo.Length != parsedVersion.FileLength) { Console.WriteLine("Downloaded file length ({0}) differs from length in VersionInfo.txt {1}, thus the downloaded file will be deleted!", fileInfo.Length, parsedVersion.FileLength); fileInfo.Delete(); } else { Console.WriteLine("Test file length of downloaded package file ... ok!"); } } } } }