Ejemplo n.º 1
0
        public override async Task <int> Execute()
        {
            try
            {
                string file;
                ModificationPackageBuilderAction action;

                var config = new ModificationPackageConfig
                {
                    Name              = this.Verb.Name,
                    Publisher         = this.Verb.PublisherName,
                    DisplayName       = this.Verb.DisplayName,
                    DisplayPublisher  = this.Verb.PublisherDisplayName,
                    Version           = this.Verb.Version,
                    IncludeVfsFolders = this.Verb.CopyFolderStructure
                };

                if (string.Equals(".msix", Path.GetExtension(this.Verb.OutputPath), StringComparison.OrdinalIgnoreCase))
                {
                    file   = this.Verb.OutputPath;
                    action = ModificationPackageBuilderAction.Msix;
                }
                else
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    file   = Path.Combine(this.Verb.OutputPath, "AppxManifest.xml");
                    action = ModificationPackageBuilderAction.Manifest;
                }

                config.ParentPackagePath = this.Verb.ParentPackagePath;
                config.ParentName        = this.Verb.ParentName;
                config.ParentPublisher   = this.Verb.ParentPublisher;

                if (!string.IsNullOrEmpty(this.Verb.IncludeRegFile))
                {
                    config.IncludeRegistry = new FileInfo(this.Verb.IncludeRegFile);
                }

                if (!string.IsNullOrEmpty(this.Verb.IncludeFolder))
                {
                    config.IncludeFolder = new DirectoryInfo(this.Verb.IncludeFolder);
                }

                await this.appxContentBuilder.Create(config, file, action).ConfigureAwait(false);

                await this.Console.WriteSuccess($"Modification package created in {file}.").ConfigureAwait(false);

                return(0);
            }
            catch (Exception e)
            {
                Logger.Error(e);
                await this.Console.WriteError(e.Message).ConfigureAwait(false);

                return(1);
            }
        }
Ejemplo n.º 2
0
        public async Task Create(ModificationPackageConfig config, string filePath, ModificationPackageBuilderAction action, CancellationToken cancellation = default, IProgress <ProgressData> progress = default)
        {
            var fileInfo = new FileInfo(filePath);

            if (fileInfo.Directory != null && !fileInfo.Directory.Exists)
            {
                fileInfo.Directory.Create();
            }

            var modPackageTemplate = GetBundledResourcePath("ModificationPackage.AppxManifest.xml");
            var logoPath           = GetBundledResourcePath("Logo.png");

            string manifestContent;

            using (var fs = File.OpenRead(modPackageTemplate))
            {
                var xmlDoc = await XDocument.LoadAsync(fs, LoadOptions.None, cancellationToken : cancellation).ConfigureAwait(false);

                await this.PrepareModificationPackage(xmlDoc, config).ConfigureAwait(false);

                manifestContent = xmlDoc.ToString(SaveOptions.OmitDuplicateNamespaces);
            }

            if (action == ModificationPackageBuilderAction.Manifest)
            {
                using (var sourceStream = File.OpenRead(logoPath))
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    var assetsDirectory = Path.Combine(Path.GetDirectoryName(filePath), "Assets");
                    if (!Directory.Exists(assetsDirectory))
                    {
                        Directory.CreateDirectory(assetsDirectory);
                    }

                    using (var targetStream = File.OpenWrite(Path.Combine(assetsDirectory, "Logo.png")))
                    {
                        await sourceStream.CopyToAsync(targetStream, cancellation).ConfigureAwait(false);
                    }
                }

                if (config.IncludeVfsFolders && config.ParentPackagePath != null)
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    this.CopyVfsStructure(config.ParentPackagePath, new DirectoryInfo(Path.GetDirectoryName(filePath)));
                }

                if (config.IncludeFolder != null)
                {
                    if (!config.IncludeFolder.Exists)
                    {
                        throw new DirectoryNotFoundException($"The directory folder '{config.IncludeFolder.FullName}' does not exist.");
                    }

                    // ReSharper disable once AssignNullToNotNullAttribute
                    await this.CopyFolder(config.IncludeFolder, new DirectoryInfo(Path.GetDirectoryName(filePath)), cancellation).ConfigureAwait(false);
                }

                if (config.IncludeRegistry?.Exists == true)
                {
                    if (!config.IncludeRegistry.Exists)
                    {
                        throw new FileNotFoundException(
                                  $"The file '{config.IncludeRegistry.FullName}' does not exist.");
                    }

                    // ReSharper disable once AssignNullToNotNullAttribute
                    await this.CopyRegistry(config.IncludeRegistry, new DirectoryInfo(Path.GetDirectoryName(filePath))).ConfigureAwait(false);
                }

                await File.WriteAllTextAsync(filePath, manifestContent, Encoding.UTF8, cancellation).ConfigureAwait(false);

                return;
            }

            var tempFolder = Environment.ExpandEnvironmentVariables(@"%temp%\msix-hero-" + Guid.NewGuid().ToString("N").Substring(10));

            try
            {
                using (var sourceStream = File.OpenRead(logoPath))
                {
                    var assetsFolder = Path.Combine(tempFolder, "Assets");
                    if (!Directory.Exists(assetsFolder))
                    {
                        Directory.CreateDirectory(assetsFolder);
                    }

                    using (var targetStream = File.OpenWrite(Path.Combine(assetsFolder, "Logo.png")))
                    {
                        await sourceStream.CopyToAsync(targetStream, cancellation).ConfigureAwait(false);
                    }
                }

                if (config.IncludeVfsFolders && config.ParentPackagePath != null)
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    this.CopyVfsStructure(config.ParentPackagePath, new DirectoryInfo(tempFolder));
                }

                if (config.IncludeFolder != null)
                {
                    if (!config.IncludeFolder.Exists)
                    {
                        throw new DirectoryNotFoundException($"The directory folder '{config.IncludeFolder.FullName}' does not exist.");
                    }

                    // ReSharper disable once AssignNullToNotNullAttribute
                    await this.CopyFolder(config.IncludeFolder, new DirectoryInfo(tempFolder), cancellation).ConfigureAwait(false);
                }

                if (config.IncludeRegistry != null)
                {
                    if (!config.IncludeRegistry.Exists)
                    {
                        throw new FileNotFoundException($"The file '{config.IncludeRegistry.FullName}' does not exist.");
                    }

                    await this.CopyRegistry(config.IncludeRegistry, new DirectoryInfo(tempFolder)).ConfigureAwait(false);
                }

                var manifestPath = new FileInfo(Path.Join(tempFolder, FileConstants.AppxManifestFile));
                if (manifestPath.Exists)
                {
                    manifestPath.Delete();
                }
                else if (manifestPath.Directory?.Exists == false)
                {
                    manifestPath.Directory.Create();
                }

                await File.WriteAllTextAsync(manifestPath.FullName, manifestContent, Encoding.UTF8, cancellation).ConfigureAwait(false);

                await this.packer.PackFiles(tempFolder, filePath, 0, cancellation, progress).ConfigureAwait(false);
            }
            finally
            {
                try
                {
                    if (Directory.Exists(tempFolder))
                    {
                        Directory.Delete(tempFolder, true);
                    }
                }
                catch (Exception e)
                {
                    Logger.Warn(e, "Clean-up failed.");
                }
            }
        }
Ejemplo n.º 3
0
        private async Task PrepareModificationPackage(XDocument template, ModificationPackageConfig config)
        {
            XNamespace nsUap4           = "http://schemas.microsoft.com/appx/manifest/uap/windows10/4";
            XNamespace nsUap6           = "http://schemas.microsoft.com/appx/manifest/uap/windows10/6";
            XNamespace nsRescap         = "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities";
            XNamespace nsRescap6        = "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/6";
            XNamespace nsBuild          = "http://schemas.microsoft.com/developer/appx/2015/build";
            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();
            }

            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));
            }

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

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

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

            var package      = GetOrCreateNode(template, "Package", defaultNamespace);
            var dependencies = GetOrCreateNode(package, "Dependencies", defaultNamespace);

            var dependency = new XElement(nsUap4 + "MainPackageDependency");

            dependencies.Add(dependency);

            var parentName      = config.ParentName;
            var parentPublisher = config.ParentPublisher;

            if (string.IsNullOrEmpty(parentPublisher) || string.IsNullOrEmpty(parentName))
            {
                IAppxFileReader reader = null;
                try
                {
                    if (string.Equals(FileConstants.AppxManifestFile, Path.GetFileName(config.ParentPackagePath), StringComparison.OrdinalIgnoreCase))
                    {
                        reader = new FileInfoFileReaderAdapter(config.ParentPackagePath);
                    }
                    else
                    {
                        reader = new ZipArchiveFileReaderAdapter(config.ParentPackagePath);
                    }

                    var manifestReader = new AppxManifestReader();
                    var read           = await manifestReader.Read(reader).ConfigureAwait(false);

                    if (string.IsNullOrEmpty(parentPublisher))
                    {
                        parentPublisher = read.Publisher;
                    }

                    if (string.IsNullOrEmpty(parentName))
                    {
                        parentName = read.Name;
                    }
                }
                finally
                {
                    reader?.Dispose();
                }
            }

            dependency.SetAttributeValue("Name", parentName);
            dependency.SetAttributeValue("Publisher", parentPublisher);

            var identity = GetOrCreateNode(package, "Identity", defaultNamespace);

            identity.SetAttributeValue("Name", config.Name);
            identity.SetAttributeValue("Publisher", config.Publisher);

            var fixVersion = Version.Parse(config.Version);

            var major    = fixVersion.Major;
            var minor    = fixVersion.Minor;
            var build    = fixVersion.Build;
            var revision = fixVersion.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;
            }

            identity.SetAttributeValue("Version", new Version(major, minor, build, revision).ToString(4));

            var properties = GetOrCreateNode(package, "Properties", defaultNamespace);

            GetOrCreateNode(properties, "DisplayName", defaultNamespace).Value          = config.DisplayName ?? "Modification Package Name";
            GetOrCreateNode(properties, "PublisherDisplayName", defaultNamespace).Value = config.DisplayPublisher ?? "Modification Package Publisher Name";
            GetOrCreateNode(properties, "Description", defaultNamespace).Value          = "Modification Package for " + parentName;
            GetOrCreateNode(properties, "Logo", defaultNamespace).Value         = "Assets\\Logo.png";
            GetOrCreateNode(properties, "ModificationPackage", nsRescap6).Value = "true";

            var branding = new MsixHeroBrandingInjector();

            branding.Inject(template);
        }
Ejemplo n.º 4
0
        protected override async Task <bool> Save(CancellationToken cancellationToken, IProgress <ProgressData> progress)
        {
            if (!this.IsValid)
            {
                return(false);
            }

            // ReSharper disable once NotAccessedVariable
            string selectedPath;

            switch (this.Create.CurrentValue)
            {
            case ModificationPackageBuilderAction.Manifest:
                if (!this.interactionService.SelectFolder(out selectedPath))
                {
                    return(false);
                }

                selectedPath = Path.Join(selectedPath, "AppxManifest.xml");
                break;

            case ModificationPackageBuilderAction.Msix:
            case ModificationPackageBuilderAction.SignedMsix:
                if (!this.interactionService.SaveFile(FileDialogSettings.FromFilterString("MSIX Modification Packages|*.msix"), out selectedPath))
                {
                    return(false);
                }

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var modificationPkgCreationRequest = new ModificationPackageConfig
            {
                DisplayName       = this.DisplayName.CurrentValue,
                Name              = this.Name.CurrentValue,
                Publisher         = this.PublisherName.CurrentValue,
                DisplayPublisher  = this.PublisherDisplayName.CurrentValue,
                Version           = this.Version.CurrentValue,
                ParentName        = this.ParentName.CurrentValue,
                ParentPublisher   = this.ParentPublisher.CurrentValue,
                IncludeVfsFolders = this.IncludeVfsFolders.CurrentValue && this.IsIncludeVfsFoldersEnabled,
                IncludeFolder     = this.IncludeFiles.CurrentValue && !string.IsNullOrEmpty(this.SourceFolder.CurrentValue) ? new DirectoryInfo(this.SourceFolder.CurrentValue) : null,
                IncludeRegistry   = this.IncludeRegistry.CurrentValue && !string.IsNullOrEmpty(this.SourceRegistryFile.CurrentValue) ? new FileInfo(this.SourceRegistryFile.CurrentValue) : null,
                ParentPackagePath = this.SourcePath.CurrentValue
            };

            await this.contentBuilder.Create(modificationPkgCreationRequest, selectedPath, this.Create.CurrentValue, cancellationToken, progress).ConfigureAwait(false);

            switch (this.Create.CurrentValue)
            {
            case ModificationPackageBuilderAction.Manifest:
                this.Result = selectedPath;
                break;

            case ModificationPackageBuilderAction.Msix:
                this.Result = selectedPath;
                break;

            case ModificationPackageBuilderAction.SignedMsix:

                var manager = await this.signingManagerFactory.GetProxyFor(SelfElevationLevel.AsInvoker, cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                switch (this.TabCertificate.Store.CurrentValue)
                {
                case CertificateSource.Pfx:
                    await manager.SignPackageWithPfx(selectedPath, true, this.TabCertificate.PfxPath.CurrentValue, this.TabCertificate.Password.CurrentValue, this.TabCertificate.TimeStamp.CurrentValue, IncreaseVersionMethod.None, cancellationToken, progress).ConfigureAwait(false);

                    break;

                case CertificateSource.Personal:
                    await manager.SignPackageWithInstalled(selectedPath, true, this.TabCertificate.SelectedPersonalCertificate?.CurrentValue?.Model, this.TabCertificate.TimeStamp.CurrentValue, IncreaseVersionMethod.None, cancellationToken, progress).ConfigureAwait(false);

                    break;

                case CertificateSource.DeviceGuard:
                    await manager.SignPackageWithDeviceGuardFromUi(selectedPath, this.TabCertificate.DeviceGuard.CurrentValue, this.TabCertificate.TimeStamp.CurrentValue, IncreaseVersionMethod.None, cancellationToken, progress).ConfigureAwait(false);

                    break;
                }

                this.Result = selectedPath;
                break;
            }

            return(true);
        }
        public override async Task <int> Execute()
        {
            try
            {
                string file;
                ModificationPackageBuilderAction action;

                var config = new ModificationPackageConfig
                {
                    Name              = this.Verb.Name,
                    Publisher         = this.Verb.PublisherName,
                    DisplayName       = this.Verb.DisplayName,
                    DisplayPublisher  = this.Verb.PublisherDisplayName,
                    Version           = this.Verb.Version,
                    IncludeVfsFolders = this.Verb.CopyFolderStructure
                };

                switch (Path.GetExtension(this.Verb.OutputPath)?.ToLowerInvariant())
                {
                case FileConstants.MsixExtension:
                case FileConstants.AppxExtension:
                {
                    file   = this.Verb.OutputPath;
                    action = ModificationPackageBuilderAction.Msix;
                    break;
                }

                default:
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    file   = Path.Combine(this.Verb.OutputPath, FileConstants.AppxManifestFile);
                    action = ModificationPackageBuilderAction.Manifest;
                    break;
                }
                }

                config.ParentPackagePath = this.Verb.ParentPackagePath;
                config.ParentName        = this.Verb.ParentName;
                config.ParentPublisher   = this.Verb.ParentPublisher;

                if (!string.IsNullOrEmpty(this.Verb.IncludeRegFile))
                {
                    config.IncludeRegistry = new FileInfo(this.Verb.IncludeRegFile);
                }

                if (!string.IsNullOrEmpty(this.Verb.IncludeFolder))
                {
                    config.IncludeFolder = new DirectoryInfo(this.Verb.IncludeFolder);
                }

                await this.modificationPackageBuilder.Create(config, file, action).ConfigureAwait(false);

                await this.Console.WriteSuccess($"Modification package created in {file}.").ConfigureAwait(false);

                return(StandardExitCodes.ErrorSuccess);
            }
            catch (Exception e)
            {
                Logger.Error(e);
                await this.Console.WriteError(e.Message).ConfigureAwait(false);

                return(StandardExitCodes.ErrorGeneric);
            }
        }