private async Task AdjustManifest(XDocument template, AppxManifestCreatorOptions config, DirectoryInfo baseDirectory, string[] entryPoints)
        {
            XNamespace nsUap = "http://schemas.microsoft.com/appx/manifest/uap/windows10";
            XNamespace nsUap4 = "http://schemas.microsoft.com/appx/manifest/uap/windows10/4";
            XNamespace nsUap6 = "http://schemas.microsoft.com/appx/manifest/uap/windows10/6";
            XNamespace defaultNamespace = "http://schemas.microsoft.com/appx/manifest/foundation/windows10";

            var root = template.Root;
            if (root == null)
            {
                root = new XElement(defaultNamespace + "Package");
                template.Add(root);
            }
            else
            {
                defaultNamespace = root.GetDefaultNamespace();
            }

            // Add capability
            var addCapability = new AddCapability("runFullTrust");
            var capabilityExecutor = new AddCapabilityExecutor(template);
            await capabilityExecutor.Execute(addCapability).ConfigureAwait(false);

            // Set identity
            var setIdentity = new SetPackageIdentity
            {
                Name = config.PackageName,
                Publisher = config.PublisherName,
                ProcessorArchitecture = config.PackageArchitecture.ToString("G").ToLowerInvariant()
            };

            var major = config.Version.Major;
            var minor = config.Version.Minor;
            var build = config.Version.Build;
            var revision = config.Version.Revision;

            if (major < 0)
            {
                throw new FormatException("Invalid version format, major version is required.");
            }

            if (minor < 0)
            {
                throw new FormatException("Invalid version format, major version is required.");
            }

            if (revision < 0)
            {
                revision = 0;
            }

            if (build < 0)
            {
                build = 0;
            }

            setIdentity.Version = new Version(major, minor, build, revision).ToString();
            var executor = new SetPackageIdentityExecutor(template);
            await executor.Execute(setIdentity).ConfigureAwait(false);

            // Add namespaces (legacy)
            if (root.GetPrefixOfNamespace(nsUap) == null)
            {
                root.Add(new XAttribute(XNamespace.Xmlns + "uap", nsUap.NamespaceName));
            }

            if (root.GetPrefixOfNamespace(nsUap4) == null)
            {
                root.Add(new XAttribute(XNamespace.Xmlns + "uap4", nsUap6.NamespaceName));
            }

            if (root.GetPrefixOfNamespace(nsUap6) == null)
            {
                root.Add(new XAttribute(XNamespace.Xmlns + "uap6", nsUap6.NamespaceName));
            }
            
            var package = GetOrCreateNode(template, "Package", defaultNamespace);
            
            var properties = GetOrCreateNode(package, "Properties", defaultNamespace);
            GetOrCreateNode(properties, "DisplayName", defaultNamespace).Value = config.PackageDisplayName ?? config.PackageName ?? "DisplayName";
            GetOrCreateNode(properties, "Description", defaultNamespace).Value = config.PackageDisplayName ?? config.PackageName ?? "Description";
            GetOrCreateNode(properties, "PublisherDisplayName", defaultNamespace).Value = config.PublisherDisplayName ?? config.PublisherName ?? "Publisher";
            GetOrCreateNode(properties, "Logo", defaultNamespace).Value = "Assets\\Logo.png";
            var applicationsNode = GetOrCreateNode(package, "Applications", defaultNamespace);

            var usedNames = new HashSet<string>();
            foreach (var item in entryPoints)
            {
                var applicationNode = this.CreateApplicationNodeFromExe(baseDirectory, item);
                applicationsNode.Add(applicationNode);

                var idCandidate = Regex.Replace(Path.GetFileNameWithoutExtension(item), "[^a-zA-z0-9_]+", string.Empty);
                if (!usedNames.Add(idCandidate))
                {
                    var index = 1;
                    var baseIdCandidate = idCandidate;
                    while (!usedNames.Add(baseIdCandidate + "_" + index))
                    {
                        index++;
                    }

                    idCandidate = baseIdCandidate + "_" + index;
                }

                applicationNode.SetAttributeValue("Id", idCandidate);
            }

            var branding = new MsixHeroBrandingInjector();
            await branding.Inject(template, MsixHeroBrandingInjector.BrandingInjectorOverrideOption.PreferIncoming).ConfigureAwait(false);
        }
        public async IAsyncEnumerable<CreatedItem> CreateManifestForDirectory(
            DirectoryInfo sourceDirectory,
            AppxManifestCreatorOptions options = default,
            [EnumeratorCancellation] CancellationToken cancellationToken = default,
            IProgress<Progress> progress = null)
        {
            options ??= AppxManifestCreatorOptions.Default;
            
            // Add logo to assets if there is nothing
            if (options.CreateLogo)
            {
                CreatedItem logo = default;
                foreach (var entryPoint in options.EntryPoints ?? Enumerable.Empty<string>())
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        var entryPointPath = new FileInfo(Path.Combine(sourceDirectory.FullName, entryPoint));
                        if (entryPointPath.Exists)
                        {
                            logo = await this.CreateLogo(entryPointPath).ConfigureAwait(false);
                        }
                    }
                    // ReSharper disable once EmptyGeneralCatchClause
                    catch
                    {
                    }

                    if (!default(CreatedItem).Equals(logo))
                    {
                        break;
                    }
                }

                if (default(CreatedItem).Equals(logo))
                {
                    logo = await this.CreateDefaultLogo(cancellationToken).ConfigureAwait(false);
                }

                yield return logo;
            }
            
            if (options.RegistryFile?.Exists == true)
            {
                await foreach (var registryItem in this.CreateRegistryEntries(options.RegistryFile).ConfigureAwait(false))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    if (!registryItem.Equals(default(CreatedItem)))
                    {
                        yield return registryItem;
                    }
                }
            }

            // The actual part - create the manifest
            var modPackageTemplate = GetBundledResourcePath("ModificationPackage.AppxManifest.xml");
            await using var openTemplate = File.OpenRead(modPackageTemplate);
            var xml = await XDocument.LoadAsync(openTemplate, LoadOptions.None, cancellationToken).ConfigureAwait(false);
            var entryPoints = options.EntryPoints;

            if (entryPoints?.Any() != true)
            {
                var getExeFiles = await this.GetEntryPointCandidates(sourceDirectory, cancellationToken).ConfigureAwait(false);
                entryPoints = getExeFiles.ToArray();
            }

            if (options.EntryPoints?.Any() == true)
            {
                foreach (var entryPoint in options.EntryPoints)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    ExceptionGuard.Guard(() =>
                    {
                        var fvi = FileVersionInfo.GetVersionInfo(Path.Combine(sourceDirectory.FullName, entryPoint));

                        if (options.Version == null)
                        {
                            options.Version = Version.TryParse(fvi.ProductVersion ?? fvi.FileVersion ?? "#", out var v) ? v : null;
                        }

                        if (string.IsNullOrEmpty(options.PackageName) && !string.IsNullOrEmpty(Sanitize(fvi.ProductName)))
                        {
                            options.PackageName = Sanitize(fvi.ProductName, "ProductName")?.Trim();
                        }

                        if (string.IsNullOrEmpty(options.PackageDisplayName) && !string.IsNullOrEmpty(fvi.ProductName))
                        {
                            options.PackageDisplayName = fvi.ProductName?.Trim();
                        }

                        if (string.IsNullOrEmpty(options.PublisherName) && !string.IsNullOrEmpty(Sanitize(fvi.CompanyName)))
                        {
                            options.PublisherName = "CN=" + Sanitize(fvi.CompanyName, "CompanyName");
                        }

                        if (string.IsNullOrEmpty(options.PublisherDisplayName) && !string.IsNullOrEmpty(Sanitize(fvi.CompanyName)))
                        {
                            options.PublisherDisplayName = fvi.CompanyName?.Trim();
                        }
                    });

                    if (options.Version != null &&
                        !string.IsNullOrEmpty(options.PublisherName) &&
                        !string.IsNullOrEmpty(options.PublisherDisplayName) &&
                        !string.IsNullOrEmpty(options.PackageName) &&
                        !string.IsNullOrEmpty(options.PackageDisplayName))
                    {
                        break;
                    }
                }
            }

            if (string.IsNullOrEmpty(options.PackageDisplayName))
            {
                options.PackageDisplayName = "MyPackage";
            }

            if (string.IsNullOrEmpty(options.PackageName))
            {
                options.PackageName = "MyPackage";
            }

            if (string.IsNullOrEmpty(options.PublisherName))
            {
                options.PublisherName = "CN=Publisher";
            }

            if (string.IsNullOrEmpty(options.PublisherDisplayName))
            {
                options.PublisherDisplayName = "Publisher";
            }

            if (options.Version == null)
            {
                options.Version = new Version(1, 0, 0);
            }

            await this.AdjustManifest(xml, options, sourceDirectory, entryPoints).ConfigureAwait(false);
            var manifestContent = xml.ToString(SaveOptions.OmitDuplicateNamespaces);
            
            var manifestFilePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(FileConstants.AppxManifestFile) + "-" + Guid.NewGuid().ToString("N").Substring(0, 10) + ".xml");
            await File.WriteAllTextAsync(manifestFilePath, manifestContent, Encoding.UTF8, cancellationToken);

            yield return CreatedItem.CreateManifest(manifestFilePath);
        }