Inheritance: IDisposable
        public async Task <string> GetLatestVersionAsync(baseURL branchUrl, OfficeEdition officeEdition)
        {
            var fileName = "v32.cab";

            if (officeEdition == OfficeEdition.Office64Bit)
            {
                fileName = "v64.cab";
            }

            var guid = Guid.NewGuid().ToString();

            var vcabFileDir = Environment.ExpandEnvironmentVariables(@"%temp%\OfficeProPlus\" + branchUrl.Branch + @"\" + guid);

            var vcabFilePath    = vcabFileDir + @"\" + fileName;
            var vcabExtFilePath = vcabFileDir + @"\ExtractedFiles\VersionDescriptor.xml";

            Directory.CreateDirectory(vcabFileDir);

            var fd = new FileDownloader();
            await fd.DownloadAsync(branchUrl.URL + @"/Office/Data/" + fileName, vcabFilePath);

            var cabExtractor = new CabExtractor(vcabFilePath);

            cabExtractor.ExtractCabFiles();

            var version = GetCabVersion(vcabExtFilePath);

            return(version);
        }
        public async Task <List <UpdateChannel> > DownloadReleaseHistoryCabAsync()
        {
            var guid = Guid.NewGuid().ToString();

            var cabPath = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid);

            Directory.CreateDirectory(cabPath);

            var savePath           = Environment.ExpandEnvironmentVariables(@"%temp%\ReleaseHistory.xml");
            var releaseHistoryPath = "";

            var localCabPath = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\" + guid + ".cab");

            try
            {
                var now = DateTime.Now;

                var tmpReleaseHistory =
                    Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour +
                                                           "_ReleaseHistory.xml");
                using (var releaser = await myLock.LockAsync())
                {
                    if (File.Exists(localCabPath))
                    {
                        File.Delete(localCabPath);
                    }

                    if (!File.Exists(tmpReleaseHistory))
                    {
                        if (!File.Exists(localCabPath))
                        {
                            var fd = new FileDownloader();
                            await fd.DownloadAsync(OfficeVersionHistoryUrl, localCabPath);
                        }
                        var cabExtractor = new CabExtractor(localCabPath);
                        cabExtractor.ExtractCabFiles();
                    }

                    var dirInfo = new DirectoryInfo(Environment.ExpandEnvironmentVariables(@"%temp%"));
                    foreach (var file in dirInfo.GetFiles("*_ReleaseHistory.xml"))
                    {
                        try
                        {
                            if (!file.FullName.Equals(tmpReleaseHistory, StringComparison.InvariantCultureIgnoreCase))
                            {
                                File.Delete(file.FullName);
                            }
                        }
                        catch (Exception ex)
                        {
                        }
                    }

                    releaseHistoryPath =
                        Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\ExtractedFiles\ReleaseHistory.xml");
                    if (File.Exists(tmpReleaseHistory))
                    {
                        releaseHistoryPath = tmpReleaseHistory;
                    }
                    else
                    {
                        Retry.Block(10, 1, () => File.Copy(releaseHistoryPath, tmpReleaseHistory, true));
                    }
                }
            }
            catch (Exception ex)
            {
                releaseHistoryPath = savePath;
            }

            var releaseHistory = GenerateReleaseHistory(releaseHistoryPath);

            try
            {
                using (var releaser = await myLock.LockAsync())
                {
                    if (!string.IsNullOrEmpty(releaseHistoryPath))
                    {
                        if (File.Exists(releaseHistoryPath))
                        {
                            if (releaseHistoryPath != savePath)
                            {
                                File.Copy(releaseHistoryPath, savePath, true);
                            }
                        }
                    }
                    if (File.Exists(localCabPath))
                    {
                        File.Delete(localCabPath);
                    }
                    if (Directory.Exists(cabPath))
                    {
                        Directory.Delete(cabPath, true);
                    }
                }
            }
            catch { }

            return(releaseHistory);
        }
        public async Task <List <UpdateFiles> > DownloadCabAsync()
        {
            var guid = Guid.NewGuid().ToString();

            var cabPath = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid);

            Directory.CreateDirectory(cabPath);

            var localCabPath = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\" + guid + ".cab");

            if (File.Exists(localCabPath))
            {
                File.Delete(localCabPath);
            }

            var now = DateTime.Now;

            var tmpFile32 = Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour + "_32.xml");
            var tmpFile64 = Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour + "_64.xml");

            if (!File.Exists(tmpFile32) || !File.Exists(tmpFile64))
            {
                using (var releaser = await myLock.LockAsync())
                {
                    var tmpFile =
                        Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour +
                                                               ".cab");

                    if (File.Exists(tmpFile))
                    {
                        Retry.Block(10, 1, () => File.Copy(tmpFile, localCabPath, true));
                    }

                    if (!File.Exists(localCabPath))
                    {
                        var fd = new FileDownloader();
                        await fd.DownloadAsync(OfficeVersionUrl, localCabPath);

                        try
                        {
                            File.Copy(localCabPath, tmpFile);
                        }
                        catch
                        {
                        }
                    }

                    var cabExtractor = new CabExtractor(localCabPath);
                    cabExtractor.ExtractCabFiles();
                }
            }

            var xml32Path = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\ExtractedFiles\o365client_32bit.xml");
            var xml64Path = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\ExtractedFiles\o365client_64bit.xml");

            if (File.Exists(tmpFile32))
            {
                xml32Path = tmpFile32;
            }
            else
            {
                Retry.Block(10, 1, () => File.Copy(xml32Path, tmpFile32, true));
            }

            if (File.Exists(tmpFile64))
            {
                xml64Path = tmpFile64;
            }
            else
            {
                Retry.Block(10, 1, () => File.Copy(xml64Path, tmpFile64, true));
            }

            var updateFiles32 = GenerateUpdateFiles(xml32Path);
            var updateFiles64 = GenerateUpdateFiles(xml64Path);

            try
            {
                if (File.Exists(localCabPath))
                {
                    File.Delete(localCabPath);
                }
                if (Directory.Exists(cabPath))
                {
                    Directory.Delete(cabPath, true);
                }
            }
            catch { }

            return(new List <UpdateFiles>()
            {
                updateFiles32,
                updateFiles64
            });
        }
        public async Task<string> GetLatestVersionAsync(baseURL branchUrl, OfficeEdition officeEdition)
        {
            var fileName = "v32.cab";
            if (officeEdition == OfficeEdition.Office64Bit)
            {
                fileName = "v64.cab";
            }

            var guid = Guid.NewGuid().ToString();

            var vcabFileDir = Environment.ExpandEnvironmentVariables(@"%temp%\OfficeProPlus\" + branchUrl.Branch + @"\" + guid);

            var vcabFilePath = vcabFileDir + @"\" + fileName;
            var vcabExtFilePath = vcabFileDir + @"\ExtractedFiles\VersionDescriptor.xml";

            Directory.CreateDirectory(vcabFileDir);

            var fd = new FileDownloader();
            await fd.DownloadAsync(branchUrl.URL + @"/Office/Data/" + fileName, vcabFilePath);

            var cabExtractor = new CabExtractor(vcabFilePath);
            cabExtractor.ExtractCabFiles();

            var version = GetCabVersion(vcabExtFilePath);
            return version;
        }
        public async Task<List<UpdateFiles>> DownloadCabAsync()
        {
            var guid = Guid.NewGuid().ToString();

            var cabPath = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid);
            Directory.CreateDirectory(cabPath);
            var localCabPath = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\" + guid + ".cab");
            if (File.Exists(localCabPath)) File.Delete(localCabPath);

            var now = DateTime.Now;

            var tmpFile32 = Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour + "_32.xml");
            var tmpFile64 = Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour + "_64.xml");

            if (!File.Exists(tmpFile32) || !File.Exists(tmpFile64))
            {
                using (var releaser = await myLock.LockAsync())
                {
                    var tmpFile =
                        Environment.ExpandEnvironmentVariables(@"%temp%\" + now.Year + now.Month + now.Day + now.Hour +
                                                               ".cab");

                    if (File.Exists(tmpFile))
                    {
                        Retry.Block(10, 1, () => File.Copy(tmpFile, localCabPath, true));
                    }

                    if (!File.Exists(localCabPath))
                    {
                        var fd = new FileDownloader();
                        await fd.DownloadAsync(OfficeVersionUrl, localCabPath);
                        try
                        {
                            File.Copy(localCabPath, tmpFile);
                        }
                        catch
                        {
                        }
                    }

                    var cabExtractor = new CabExtractor(localCabPath);
                    cabExtractor.ExtractCabFiles();
                }
            }

            var xml32Path = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\ExtractedFiles\o365client_32bit.xml");
            var xml64Path = Environment.ExpandEnvironmentVariables(@"%temp%\" + guid + @"\ExtractedFiles\o365client_64bit.xml");

            if (File.Exists(tmpFile32))
            {
                xml32Path = tmpFile32;
            }
            else
            {
                Retry.Block(10, 1, () => File.Copy(xml32Path, tmpFile32, true));
            }

            if (File.Exists(tmpFile64))
            {
                xml64Path = tmpFile64;
            }
            else
            {
                Retry.Block(10, 1, () => File.Copy(xml64Path, tmpFile64, true));
            }

            var updateFiles32 = GenerateUpdateFiles(xml32Path);
            var updateFiles64 = GenerateUpdateFiles(xml64Path);

            try
            {
                if (File.Exists(localCabPath)) File.Delete(localCabPath);
                if (Directory.Exists(cabPath)) Directory.Delete(cabPath, true);
            }
            catch { }

            return new List<UpdateFiles>()
            {
                updateFiles32,
                updateFiles64
            };
        }
        private async Task GenerateInstall(bool sign)
        {
            await Task.Run(async () =>
            {
                try
                {
                    var remoteLogPath = "";
                    if (GlobalObjects.ViewModel.RemoteLoggingPath != null &&
                        !string.IsNullOrEmpty(GlobalObjects.ViewModel.RemoteLoggingPath))
                    {
                        remoteLogPath = GlobalObjects.ViewModel.RemoteLoggingPath;
                    }
                    FixFileExtension();
                    var executablePath = "";

                    for (var i = 1; i <= 2; i++)
                    {
                        await Dispatcher.InvokeAsync(() =>
                        {
                            executablePath = FileSavePath.Text.Trim();
                            WaitImage.Visibility = Visibility.Visible;
                            GenerateButton.IsEnabled = false;
                            PreviousButton.IsEnabled = false;
                            GenerateButton.Content = "";
                            PreviousButton.Content = "";

                            if (string.IsNullOrEmpty(executablePath))
                            {
                                if (i == 1)
                                {
                                    GetSaveFilePath();
                                }
                            }
                        });

                        if (!string.IsNullOrEmpty(executablePath))
                        {
                            if (executablePath.ToLower().EndsWith(".exe") || executablePath.ToLower().EndsWith(".msi"))
                            {
                                break;
                            }
                            else
                            {
                                await Dispatcher.InvokeAsync(GetSaveFilePath);
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(executablePath))
                    {
                        //throw (new Exception("File Path Required"));
                        return;
                    }

                    var directoryPath = System.IO.Path.GetDirectoryName(executablePath);
                    if (directoryPath != null)
                    {
                        if (!Directory.Exists(directoryPath))
                        {
                            var result = MessageBox.Show("The directory '" + directoryPath + "' does not exist." + Environment.NewLine + Environment.NewLine + "Create Directory?", "Create Directory", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
                            Directory.CreateDirectory(directoryPath);

                            await Dispatcher.InvokeAsync(() => { OpenExeFolderButton.IsEnabled = true; });
                        }
                    }

                    var configFilePath = Environment.ExpandEnvironmentVariables(@"%temp%\OfficeProPlus\" + Guid.NewGuid().ToString() + ".xml");
                    Directory.CreateDirectory(Environment.ExpandEnvironmentVariables(@"%temp%\OfficeProPlus"));

                    GlobalObjects.ViewModel.ConfigXmlParser.ConfigurationXml.Logging = new ODTLogging
                    {
                        Level = LoggingLevel.Standard, Path = @"%temp%"
                    };

                    System.IO.File.WriteAllText(configFilePath, GlobalObjects.ViewModel.ConfigXmlParser.Xml);

                    string sourceFilePath = null;
                    await Dispatcher.InvokeAsync(() =>
                    {
                        if (IncludeBuild.IsChecked.HasValue && IncludeBuild.IsChecked.Value)
                        {
                            sourceFilePath = BuildFilePath.Text.Trim();
                            if (string.IsNullOrEmpty(sourceFilePath)) sourceFilePath = null;
                        }
                    });

                    var isInstallExe = false;
                    await Dispatcher.InvokeAsync(() => { isInstallExe = InstallExecutable.IsChecked.HasValue && InstallExecutable.IsChecked.Value; });

                    var configXml = GlobalObjects.ViewModel.ConfigXmlParser.ConfigurationXml;
                    string version = null;
                    if (configXml.Add.Version != null)
                    {
                        version = configXml.Add.Version.ToString();
                    }


                    if (!string.IsNullOrEmpty(sourceFilePath))
                    {
                        var branchName = "";
                        if (configXml.Add?.Branch != null)
                        {
                            branchName = configXml.Add.Branch.ToString();
                        }
                        if (configXml.Add?.ODTChannel != null)
                        {
                            branchName = configXml.Add.ODTChannel.ToString();
                        }

                        var languages = new List<string>();
                        foreach (var product in configXml.Add.Products)
                        {
                            foreach (var languageItem in product.Languages)
                            {
                                languages.Add(languageItem.ID);
                            }
                        }

                        var edition = OfficeEdition.Office32Bit;
                        if (configXml.Add.OfficeClientEdition == OfficeClientEdition.Office64Bit)
                        {
                            edition = OfficeEdition.Office64Bit;
                        }

                        var ppDownload = new ProPlusDownloader();
                        var validFiles = await ppDownload.ValidateSourceFiles(new DownloadBranchProperties()
                        {
                            TargetDirectory = sourceFilePath,                            
                            BranchName = branchName,
                            Languages = languages,
                            OfficeEdition = edition,
                            Version = version
                        });

                        var cabFilePath = sourceFilePath + @"\Office\Data\v32.cab";
                        if (configXml.Add.OfficeClientEdition == OfficeClientEdition.Office64Bit)
                        {
                            cabFilePath = sourceFilePath + @"\Office\Data\v64.cab";
                        }

                        if (string.IsNullOrEmpty(version) && System.IO.File.Exists(cabFilePath))
                        {
                            var fInfo = new FileInfo(cabFilePath);
                            var cabExtractor = new CabExtractor(cabFilePath);
                            cabExtractor.ExtractCabFiles();
                            cabExtractor.Dispose();

                            var vdPathDir = fInfo.Directory?.FullName + @"\ExtractedFiles";
                            var vdPath = vdPathDir + @"\VersionDescriptor.xml";
                            if (System.IO.File.Exists(vdPath))
                            {
                                var latestVersion = ppDownload.GetCabVersion(vdPath);
                                if (latestVersion != null)
                                {
                                    version = latestVersion;
                                }
                                if (Directory.Exists(vdPathDir))
                                {
                                    try
                                    {
                                        Directory.Delete(vdPathDir);
                                    }
                                    catch (Exception ex)
                                    {
                                        var strError = ex.Message;
                                    }
                                }
                            }
                        }

                        if (!validFiles)
                        {
                            throw (new Exception(
                                "The Office Source Files are invalid. Please verify that all of the files have been downloaded."));
                        }
                    }

                    var productName = "Microsoft Office 365 ProPlus Installer";
                    var productId = Guid.NewGuid().ToString(); //"8AA11E8A-A882-45CC-B52C-80149B4CF47A";
                    var upgradeCode = "AC89246F-38A8-4C32-9110-FF73533F417C";

                    var productVersion = new Version("1.0.0");

                    await Dispatcher.InvokeAsync(() =>
                    {
                        if (MajorVersion.Value.HasValue && MinorVersion.Value.HasValue && ReleaseVersion.Value.HasValue)
                        {
                            productVersion =
                                new Version(MajorVersion.Value.Value + "." + MinorVersion.Value.Value + "." +
                                            ReleaseVersion.Value.Value);
                        }
                    });

                    var installProperties = new List<OfficeInstallProperties>();

                    if (GlobalObjects.ViewModel.ApplicationMode == ApplicationMode.LanguagePack)
                    {
                        productName = "Microsoft Office 365 ProPlus Language Pack";

                        var languages = configXml?.Add?.Products?.FirstOrDefault()?.Languages;
                        foreach (var language in languages)
                        {
                            var configLangXml = new ConfigXmlParser(GlobalObjects.ViewModel.ConfigXmlParser.Xml);
                            configLangXml.ConfigurationXml.Add.ODTChannel = null;
                            var tmpProducts = configLangXml?.ConfigurationXml?.Add?.Products;
                            tmpProducts.FirstOrDefault().Languages = new List<ODTLanguage>()
                            {
                                new ODTLanguage()
                                {
                                    ID = language.ID
                                }
                            };

                            var tmpXmlFilePath = Environment.ExpandEnvironmentVariables(@"%temp%\" + Guid.NewGuid().ToString() + ".xml");
                            System.IO.File.WriteAllText(tmpXmlFilePath, configLangXml.Xml);

                            var tmpSourceFilePath = executablePath;

                            if (Regex.Match(executablePath, ".msi$", RegexOptions.IgnoreCase).Success)
                            {
                                tmpSourceFilePath = Regex.Replace(executablePath, ".msi$", "(" + language.ID + ").msi",
                                    RegexOptions.IgnoreCase);
                            }

                            if (Regex.Match(executablePath, ".exe", RegexOptions.IgnoreCase).Success)
                            {
                                tmpSourceFilePath = Regex.Replace(executablePath, ".exe$", "(" + language.ID + ").exe",
                                    RegexOptions.IgnoreCase);
                            }

                            var programFilesPath = @"%ProgramFiles%\Microsoft Office 365 ProPlus Installer\" + language.ID + @"\" + productVersion;

                            var langProductName = productName + " (" + language.ID + ")";

                            installProperties.Add(new OfficeInstallProperties()
                            {
                                ProductName = langProductName,
                                ProductId = langProductName.GenerateGuid(),
                                ConfigurationXmlPath = tmpXmlFilePath,
                                OfficeVersion = OfficeVersion.Office2016,
                                ExecutablePath = tmpSourceFilePath,
                                SourceFilePath = sourceFilePath,
                                BuildVersion = version,
                                UpgradeCode = language.ID.GenerateGuid(),
                                Version = productVersion,
                                Language = "en-us",
                                ProgramFilesPath = programFilesPath,
                                OfficeClientEdition = configXml.Add.OfficeClientEdition
                            });
                        }
                    }
                    else
                    {
                        installProperties.Add(new OfficeInstallProperties()
                        {
                            ProductName = productName,
                            ProductId = productId,
                            ConfigurationXmlPath = configFilePath,
                            OfficeVersion = OfficeVersion.Office2016,
                            ExecutablePath = executablePath,
                            SourceFilePath = sourceFilePath,
                            BuildVersion = version,
                            UpgradeCode = upgradeCode,
                            Version = productVersion,
                            Language = "en-us",
                            ProgramFilesPath = @"%ProgramFiles%\Microsoft Office 365 ProPlus Installer",
                            OfficeClientEdition = configXml.Add.OfficeClientEdition
                        });
                    }

                    foreach (var installProperty in installProperties)
                    {
                        IOfficeInstallGenerator installer = null;
                        if (isInstallExe)
                        {
                            installer = new OfficeInstallExecutableGenerator();
                            LogAnaylytics("/GenerateView", "GenerateExe");
                        }
                        else
                        {
                            installer = new OfficeInstallMsiGenerator();
                            LogAnaylytics("/GenerateView", "GenerateMSI");
                        }
                        installer.Generate(installProperty, remoteLogPath);
                    }


                    await Task.Delay(500);

                    if (!string.IsNullOrEmpty(GlobalObjects.ViewModel.SelectedCertificate.ThumbPrint) && sign)
                    {
                        await InstallerSign(executablePath);
                    }

                    if (InfoMessage != null)
                    {
                        if (isInstallExe)
                        {
                            InfoMessage(this, new MessageEventArgs()
                            {
                                Title = "Generate Executable", Message = "File Generation Complete"
                            });
                        }
                        else
                        {
                            InfoMessage(this, new MessageEventArgs()
                            {
                                Title = "Generate MSI", Message = "File Generation Complete"
                            });
                        }
                    }

                    await Task.Delay(500);
                }
                catch (Exception ex)
                {
                    LogErrorMessage(ex);
                    Console.WriteLine(ex.StackTrace);
                }
                finally
                {
                    Dispatcher.Invoke(() =>
                    {
                        WaitImage.Visibility = Visibility.Hidden;
                        GenerateButton.IsEnabled = true;
                        PreviousButton.IsEnabled = true;

                        GenerateButton.Content = "Generate";
                        PreviousButton.Content = "Previous";
                    });
                }
            });
        }