public async Task AddSimpleCapabilityWithOtherExisting()
        {
            var manifestContent = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Package
    xmlns=""http://schemas.microsoft.com/appx/manifest/foundation/windows10""
    xmlns:uap4=""http://schemas.microsoft.com/appx/manifest/uap/windows10/4""
    xmlns:uap=""http://schemas.microsoft.com/appx/manifest/uap/windows10""
    IgnorableNamespaces=""uap uap4"">
    <Capabilities>
        <uap:Capability Name=""test"" />
    </Capabilities>
</Package>";

            var manifest = XDocument.Parse(manifestContent);

            var addCapability = new AddCapability
            {
                Name = "objects3D"
            };

            var executor = new AddCapabilityExecutor(manifest);
            await executor.Execute(addCapability, CancellationToken.None);

            var allCapabilities = manifest.Root.XPathSelectElement("//*[local-name()='Capabilities']");
            var objects3d       = allCapabilities.Elements().Last();

            Assert.AreEqual("objects3D", objects3d.Attribute("Name").Value);
            Assert.AreEqual("uap", objects3d.GetPrefixOfNamespace(objects3d.Name.Namespace));
            Assert.AreEqual("uap uap4", manifest.Root.Attribute("IgnorableNamespaces").Value);
        }
        protected override async Task <int> ExecuteOnManifest(XDocument document)
        {
            var action = new AddCapability
            {
                Name = this.Verb.Name
            };

            var executor = new AddCapabilityExecutor(document);

            executor.CapabilityAdded += (_, changed) =>
            {
                if (changed.IsCustom)
                {
                    this.Console.WriteSuccess($"Added custom capability '{changed.Name}'.").GetAwaiter().GetResult();
                }
                else if (changed.IsRestricted)
                {
                    this.Console.WriteSuccess($"Added restricted capability '{changed.Name}'.").GetAwaiter().GetResult();
                }
                else
                {
                    this.Console.WriteSuccess($"Added standard capability '{changed.Name}'.").GetAwaiter().GetResult();
                }
            };

            try
            {
                await executor.Execute(action).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                await this.Console.WriteError($"Capability '{this.Verb.Name}' could not be added.").ConfigureAwait(false);

                await this.Console.WriteError(e.Message).ConfigureAwait(false);

                return(StandardExitCodes.ErrorGeneric);
            }

            return(StandardExitCodes.ErrorSuccess);
        }
        public async Task AddDeviceCapability()
        {
            var manifestContent = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Package
    xmlns:uap4=""http://schemas.microsoft.com/appx/manifest/uap/windows10/4"">
</Package>";

            var manifest = XDocument.Parse(manifestContent);

            var addCapability = new AddCapability
            {
                Name = "location"
            };

            var executor = new AddCapabilityExecutor(manifest);
            await executor.Execute(addCapability, CancellationToken.None);

            var allCapabilities = manifest.Root.XPathSelectElement("//*[local-name()='Capabilities']");
            var location        = allCapabilities.Elements().Single();

            Assert.AreEqual("location", location.Attribute("Name").Value);
        }
        public async Task AddRestrictedCapability()
        {
            var manifestContent = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Package
    xmlns:uap4=""http://schemas.microsoft.com/appx/manifest/uap/windows10/4"">
</Package>";

            var manifest = XDocument.Parse(manifestContent);

            var addCapability = new AddCapability
            {
                Name = "runFullTrust"
            };

            var executor = new AddCapabilityExecutor(manifest);
            await executor.Execute(addCapability, CancellationToken.None);

            var allCapabilities = manifest.Root.XPathSelectElement("//*[local-name()='Capabilities']");
            var runFullTrust    = allCapabilities.Elements().Single();

            Assert.AreEqual("runFullTrust", runFullTrust.Attribute("Name").Value);
            Assert.IsTrue(runFullTrust.GetPrefixOfNamespace(runFullTrust.Name.Namespace) == "rescap");
            Assert.IsTrue(manifest.Root.Attribute("IgnorableNamespaces").Value.Split(' ').Contains("rescap"));
        }
        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);
        }