/// <summary>
        /// Calculates estimated update size in bytes based on local and remote build information.
        /// </summary>
        /// <returns>The estimated update size in bytes.</returns>
        private long GetUpdateSize()
        {
            // We don't take into account potential local modified or corrupted files,
            // instead we assume that all files listed in the local build info match
            // the actual files on the local file system.
            // This is because checking the actual hashes of the files would take too
            // long for a quick update check. Instead we'll check the actual file
            // hashes when actually downloading the update.
            // This is why the calculated update size could only be an estimate
            // (although it'll be correct for everyone who doesn't modify the product).

            long updateSize = 0;

            LocalBuildInfo  lbi = localBuildInfo;
            RemoteBuildInfo rbi = remoteBuildInfo;

            foreach (var fileInfo in rbi.FileInfos)
            {
                var localMatch = lbi.FileInfos.Find(localFileInfo => localFileInfo.FilePath == fileInfo.FilePath);

                if (localMatch == null || !HashHelper.ByteArraysMatch(localMatch.Hash, fileInfo.UncompressedHash))
                {
                    updateSize += fileInfo.GetDownloadSize();
                }
            }

            return(updateSize);
        }
        private LocalBuildInfo LocalBuildInfoFromRemoteBuildInfo()
        {
            var localBuildInfo = new LocalBuildInfo();

            localBuildInfo.ProductVersionInfo = remoteBuildInfo.ProductVersionInfo;
            foreach (RemoteFileInfo fileInfo in remoteBuildInfo.FileInfos)
            {
                localBuildInfo.AddFileInfo(new LocalFileInfo(fileInfo.FilePath,
                                                             fileInfo.UncompressedHash, fileInfo.UncompressedSize));
            }
            return(localBuildInfo);
        }
        public BuildHandler(string localBuildPath, string secondStageUpdaterPath)
        {
            localBuildInfo = new LocalBuildInfo();

            if (!localBuildPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                localBuildInfo.BuildPath = localBuildPath + Path.DirectorySeparatorChar;
            }
            else
            {
                localBuildInfo.BuildPath = localBuildPath;
            }

            SecondStageUpdaterPath = secondStageUpdaterPath;
        }
Пример #4
0
        /// <summary>
        /// Writes new local and remote version files into the build directory.
        /// </summary>
        public void WriteVersionFiles()
        {
            var localBuildInfo = new LocalBuildInfo();

            localBuildInfo.ProductVersionInfo = new ProductVersionInfo(InternalVersion, DisplayedVersion);

            var remoteBuildInfo = new RemoteBuildInfo();

            remoteBuildInfo.ProductVersionInfo = new ProductVersionInfo(InternalVersion, DisplayedVersion);

            string buildPath = Environment.CurrentDirectory +
                               Path.DirectorySeparatorChar + BuildDirectory + Path.DirectorySeparatorChar;

            foreach (FileEntry file in FileEntries)
            {
                string originalFilePath = Environment.CurrentDirectory +
                                          Path.DirectorySeparatorChar + file.FilePath;

                byte[] hash = HashHelper.ComputeHashForFile(originalFilePath);
                long   size = new FileInfo(originalFilePath).Length;
                localBuildInfo.AddFileInfo(new LocalFileInfo(file.FilePath, hash, size));

                RemoteFileInfo remoteFileInfo;

                if (file.Compressed)
                {
                    string compressedFilePath = buildPath + file.FilePath + RemoteFileInfo.COMPRESSED_FILE_EXTENSION;
                    remoteFileInfo = new RemoteFileInfo(file.FilePath, hash, size, true,
                                                        HashHelper.ComputeHashForFile(compressedFilePath),
                                                        new FileInfo(compressedFilePath).Length);
                }
                else
                {
                    remoteFileInfo = new RemoteFileInfo(file.FilePath, hash, size, false);
                }

                remoteBuildInfo.AddFileInfo(remoteFileInfo);
            }

            localBuildInfo.Write(buildPath + BuildHandler.LOCAL_BUILD_INFO_FILE);
            remoteBuildInfo.Write(buildPath + BuildHandler.REMOTE_BUILD_INFO_FILE);
        }
        private void PerformUpdateInternal()
        {
            UpdaterLogger.Log("Performing update.");

            CreateTemporaryDirectory();

            UpdateMirror updateMirror = updateMirrors[lastUpdateMirrorId];

            char dsc = Path.DirectorySeparatorChar;

            string buildPath         = localBuildInfo.BuildPath;
            string downloadDirectory = buildPath + TEMPORARY_UPDATER_DIRECTORY + dsc;

            List <RemoteFileInfo> filesToDownload = GatherFilesToDownload(buildPath, downloadDirectory);

            CleanUpDownloadDirectory(filesToDownload, downloadDirectory);

            UpdaterLogger.Log("Creating downloader.");

            UpdateDownloader downloader = new UpdateDownloader();

            downloader.DownloadProgress += Downloader_DownloadProgress;
            UpdateDownloadResult result = downloader.DownloadUpdates(buildPath, downloadDirectory, filesToDownload, updateMirror);

            downloader.DownloadProgress -= Downloader_DownloadProgress;

            lock (locker)
            {
                updateInProgress = false;
            }

            switch (result.UpdateDownloadResultState)
            {
            case UpdateDownloadResultType.CANCELLED:
                UpdateCancelled?.Invoke(this, EventArgs.Empty);
                return;

            case UpdateDownloadResultType.COMPLETED:
                // If a new second-stage updater was downloaded, update it
                // first before launching it

                string originalSecondStageUpdaterPath = localBuildInfo.BuildPath + SecondStageUpdaterPath;

                string updatedSecondStageUpdaterPath = localBuildInfo.BuildPath +
                                                       TEMPORARY_UPDATER_DIRECTORY + dsc +
                                                       SecondStageUpdaterPath;

                if (File.Exists(updatedSecondStageUpdaterPath))
                {
                    File.Delete(originalSecondStageUpdaterPath);
                    File.Move(updatedSecondStageUpdaterPath, originalSecondStageUpdaterPath);
                }

                // Also update the second-stage updater's config file

                string originalSecondStageConfigPath = Path.GetDirectoryName(originalSecondStageUpdaterPath)
                                                       + dsc + SECOND_STAGE_UPDATER_CONFIGURATION_FILE;

                string updatedSecondStageConfigPath = Path.GetDirectoryName(updatedSecondStageUpdaterPath)
                                                      + dsc + SECOND_STAGE_UPDATER_CONFIGURATION_FILE;

                if (File.Exists(updatedSecondStageConfigPath))
                {
                    File.Delete(originalSecondStageConfigPath);
                    File.Move(updatedSecondStageConfigPath, originalSecondStageConfigPath);
                }

                // Generate local build information file
                LocalBuildInfo newBuildInfo = LocalBuildInfoFromRemoteBuildInfo();
                newBuildInfo.Write(localBuildInfo.BuildPath + TEMPORARY_UPDATER_DIRECTORY + dsc + LOCAL_BUILD_INFO_FILE);

                Process.Start(originalSecondStageUpdaterPath);

                // No null checking necessary here, it's actually better to
                // crash the application in case this is not subscribed to
                DownloadCompleted.Invoke(this, EventArgs.Empty);
                return;

            case UpdateDownloadResultType.FAILED:
                UpdateFailed?.Invoke(this, new UpdateFailureEventArgs(result.ErrorDescription));
                return;
            }
        }