protected sealed override async Task <int> ExecuteOnExtractedPackage(string directoryPath)
        {
            var manifestFile = Path.Combine(directoryPath, FileConstants.AppxManifestFile);

            if (!File.Exists(manifestFile))
            {
                throw new FileNotFoundException($"Manifest file {manifestFile} does not exist.");
            }

            XDocument document;
            int       result;
            {
                await using var fs = File.OpenRead(manifestFile);
                document           = await XDocument.LoadAsync(fs, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);

                var rootNode = document.Root;
                if (rootNode?.Name.LocalName != "Package")
                {
                    throw new FormatException("XML file must contain root <Package /> element.");
                }

                result = await this.ExecuteOnManifest(document).ConfigureAwait(false);

                var brandingInjector = new MsixHeroBrandingInjector();
                await brandingInjector.Inject(document).ConfigureAwait(false);
            }

            var writer = new AppxDocumentWriter(document);
            await writer.WriteAsync(manifestFile).ConfigureAwait(false);

            return(result);
        }
Пример #2
0
        public async Task Pack(
            string directory,
            string packagePath,
            IDictionary <string, string> extraFiles,
            AppxPackerOptions options           = 0,
            CancellationToken cancellationToken = default,
            IProgress <ProgressData> progress   = null)
        {
            if (!Directory.Exists(directory))
            {
                throw new DirectoryNotFoundException($"Folder {directory} does not exist.");
            }

            var fileInfo = new FileInfo(packagePath);

            if (fileInfo.Directory == null)
            {
                throw new ArgumentException($"File path {packagePath} is not supported.", nameof(packagePath));
            }

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

            var tempFile             = Path.GetTempFileName();
            var tempManifestFilePath = Path.GetTempFileName();
            var tempAutoGenerated    = Path.GetTempFileName();

            try
            {
                var inputDirectory = new DirectoryInfo(directory);

                var listBuilder = new PackageFileListBuilder();

                foreach (var item in inputDirectory.EnumerateFiles("*", SearchOption.AllDirectories))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var relativePath = Path.GetRelativePath(directory, item.FullName);

                    if (string.IsNullOrEmpty(relativePath))
                    {
                        continue;
                    }

                    // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                    if (string.Equals(FileConstants.AppxManifestFile, relativePath, StringComparison.OrdinalIgnoreCase))
                    {
                        listBuilder.AddManifest(tempManifestFilePath);
                        item.CopyTo(tempManifestFilePath, true);
                        continue;
                    }

                    listBuilder.AddFile(item.FullName, relativePath);
                }

                if (extraFiles != null)
                {
                    foreach (var item in extraFiles)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (string.Equals(Path.GetFileName(item.Key), FileConstants.AppxManifestFile, StringComparison.OrdinalIgnoreCase))
                        {
                            tempManifestFilePath = item.Value;
                            listBuilder.AddFile(item.Value, item.Key);
                        }
                        else
                        {
                            listBuilder.AddFile(item.Value, item.Key);
                        }
                    }
                }

                var allDirs = inputDirectory.EnumerateDirectories("*", SearchOption.AllDirectories);
                foreach (var emptyDir in allDirs.Where(d =>
                                                       !d.EnumerateFiles("*", SearchOption.TopDirectoryOnly).Any() &&
                                                       !d.EnumerateDirectories("*", SearchOption.TopDirectoryOnly).Any()))
                {
                    // this means we have an empty folder, which requires some special handling
                    if (new FileInfo(tempAutoGenerated).Length == 0)
                    {
                        await File.WriteAllBytesAsync(tempAutoGenerated, Array.Empty <byte>(), cancellationToken).ConfigureAwait(false);
                    }

                    var relativePath = Path.GetRelativePath(inputDirectory.FullName, emptyDir.FullName);
                    listBuilder.AddFile(tempAutoGenerated, $"{relativePath}\\GeneratedFile.txt\"");
                }

                await File.WriteAllTextAsync(tempFile, listBuilder.ToString(), Encoding.UTF8, cancellationToken).ConfigureAwait(false);

                XDocument xmlManifestDocument;
                await using (var tempManifestStream = File.OpenRead(tempManifestFilePath))
                {
                    using var tempManifestReader = new StreamReader(tempManifestStream);
                    xmlManifestDocument          = await XDocument.LoadAsync(tempManifestReader, LoadOptions.None, cancellationToken).ConfigureAwait(false);

                    var injector = new MsixHeroBrandingInjector();
                    await injector.Inject(xmlManifestDocument).ConfigureAwait(false);
                }

                cancellationToken.ThrowIfCancellationRequested();
                var appxWriter = new AppxDocumentWriter(xmlManifestDocument);
                await appxWriter.WriteAsync(tempManifestFilePath).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                var compress = !options.HasFlag(AppxPackerOptions.NoCompress);
                var validate = !options.HasFlag(AppxPackerOptions.NoValidation);

                await new MakeAppxWrapper().PackPackageFiles(tempFile, packagePath, compress, validate, cancellationToken, progress).ConfigureAwait(false);
            }
            finally
            {
                if (File.Exists(tempFile))
                {
                    File.Delete(tempFile);
                }

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

                if (File.Exists(tempAutoGenerated))
                {
                    File.Delete(tempAutoGenerated);
                }
            }
        }
 public async Task Finish(CancellationToken cancellationToken = default)
 {
     var path   = Path.Combine(this.directoryInfo.FullName, "AppxManifest.xml");
     var writer = new AppxDocumentWriter(this.manifest);
     await writer.WriteAsync(path).ConfigureAwait(false);
 }
        public override async Task <int> Execute()
        {
            try
            {
                await this.OnBegin().ConfigureAwait(false);

                if (!File.Exists(this.package) && !Directory.Exists(this.package))
                {
                    await this.Console.WriteError($"The path {this.package} does not exist.");

                    return(10);
                }

                var validation = await this.Validate().ConfigureAwait(false);

                if (validation != 0)
                {
                    return(validation);
                }

                if (File.Exists(this.package))
                {
                    // This is a file...
                    if (string.Equals(Path.GetFileName(this.package), FileConstants.AppxManifestFile, StringComparison.OrdinalIgnoreCase))
                    {
                        // .. a manifest file
                        var result = await this.ExecuteOnExtractedPackage(Path.GetDirectoryName(this.package)).ConfigureAwait(false);

                        await this.OnFinished().ConfigureAwait(false);

                        return(result);
                    }

                    if (string.Equals(".msix", Path.GetExtension(this.package)))
                    {
                        // .. an MSIX package
                        var msixMgr    = new MakeAppxWrapper();
                        var tempFolder = Path.Combine(Path.GetTempPath(), "msixhero-" + Guid.NewGuid().ToString("N").Substring(0, 8));

                        try
                        {
                            await this.Console.WriteInfo($"Opening {Path.GetFileName(this.package)}...").ConfigureAwait(false);

                            // 1) Unpack first
                            await msixMgr.UnpackPackage(this.package, tempFolder, false).ConfigureAwait(false);

                            // 2) Make edit
                            var result = await this.ExecuteOnExtractedPackage(tempFolder).ConfigureAwait(false);

                            if (result != StandardExitCodes.ErrorSuccess)
                            {
                                await this.Console.WriteWarning($"The package has not been updated due to previous errors.").ConfigureAwait(false);

                                return(result);
                            }

                            // 3) Add branding
                            XDocument document;
                            await using (var fs = File.OpenRead(Path.Combine(tempFolder, "AppxManifest.xml")))
                            {
                                document = await XDocument.LoadAsync(fs, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);
                            }

                            var inject = new MsixHeroBrandingInjector();
                            await inject.Inject(document).ConfigureAwait(false);

                            var writer = new AppxDocumentWriter(document);
                            await writer.WriteAsync(Path.Combine(tempFolder, "AppxManifest.xml")).ConfigureAwait(false);

                            if (result == StandardExitCodes.ErrorSuccess)
                            {
                                await this.Console.WriteInfo($"Saving {Path.GetFileName(this.package)}...").ConfigureAwait(false);

                                // 3) Pack again
                                await msixMgr.PackPackageDirectory(tempFolder, this.package, false, false);

                                await this.OnFinished().ConfigureAwait(false);
                            }

                            return(result);
                        }
                        finally
                        {
                            if (Directory.Exists(tempFolder))
                            {
                                ExceptionGuard.Guard(() => Directory.Delete(tempFolder, true));
                            }
                        }
                    }
                }
                else if (Directory.Exists(this.package))
                {
                    // this is extracted directory
                    var manifestPath = Path.Combine(this.package, FileConstants.AppxManifestFile);
                    if (File.Exists(manifestPath))
                    {
                        var result = await this.ExecuteOnExtractedPackage(this.package).ConfigureAwait(false);

                        XDocument document;
                        await using (var fs = File.OpenRead(manifestPath))
                        {
                            document = await XDocument.LoadAsync(fs, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);
                        }

                        var inject = new MsixHeroBrandingInjector();
                        await inject.Inject(document).ConfigureAwait(false);

                        var writer = new AppxDocumentWriter(document);
                        await writer.WriteAsync(manifestPath).ConfigureAwait(false);

                        await this.OnFinished().ConfigureAwait(false);

                        return(result);
                    }
                }

                await this.Console.WriteError($"The path {this.package} is neither a directory with extracted MSIX, an .MSIX package or a manifest file.").ConfigureAwait(false);

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

                return(StandardExitCodes.ErrorGeneric);
            }
        }