// ReSharper disable once MemberCanBeMadeStatic.Local private async Task <PsfContentViewModel> LoadPsf(IAppxFileReader source, AppxPackage manifest) { var paths = manifest.Applications.Where(a => PackageTypeConverter.GetPackageTypeFrom(a.EntryPoint, a.Executable, a.StartPage, manifest.IsFramework) == MsixPackageType.BridgePsf).Select(a => a.Executable).Where(a => a != null).Select(Path.GetDirectoryName).Where(a => !string.IsNullOrEmpty(a)).Distinct().ToList(); paths.Add(string.Empty); foreach (var items in paths) { var configJsonPath = string.IsNullOrWhiteSpace(items) ? "config.json" : Path.Combine(items, "config.json"); if (!source.FileExists(configJsonPath)) { continue; } using (var s = source.GetFile(configJsonPath)) { using var stringReader = new StreamReader(s); var all = await stringReader.ReadToEndAsync().ConfigureAwait(false); var psfSerializer = new PsfConfigSerializer(); var configJson = psfSerializer.Deserialize(all); return(new PsfContentViewModel(configJson)); } } return(null); }
public Task <AppxPackage> Read(IAppxFileReader fileReader, CancellationToken cancellationToken = default) { var isMsix = fileReader.FileExists(FileConstants.AppxManifestFile); if (isMsix) { return(this.ReadMsix(fileReader, FileConstants.AppxManifestFile, cancellationToken)); } var isAppxBundle = fileReader.FileExists(FileConstants.AppxBundleManifestFilePath); if (isAppxBundle) { throw new NotSupportedException("Bundles are not supported."); } throw new NotSupportedException("Required package source is not supported."); }
public async Task <string> GetDiskPath(IAppxFileReader fileReader, string filePath) { if (!fileReader.FileExists(filePath)) { throw new FileNotFoundException(); } await using var fileStream = fileReader.GetFile(filePath); if (fileStream is FileStream fs) { // we can assume the file is directly accessible return(fs.Name); } var index = 0; string fullPath; this.tempDirectory ??= new DirectoryInfo(Path.Combine(Path.GetTempPath(), "MSIX-Hero", Guid.NewGuid().ToString("N").Substring(10))); while (true) { fullPath = Path.Combine(this.tempDirectory.FullName, index.ToString("0"), Path.GetFileName(filePath)); if (!File.Exists(fullPath)) { break; } index++; } var fileInfo = new FileInfo(fullPath); if (fileInfo.Directory?.Exists == false) { fileInfo.Directory.Create(); } await using var targetStream = File.OpenWrite(fileInfo.FullName); await fileStream.CopyToAsync(targetStream).ConfigureAwait(false); return(fileInfo.FullName); }
public bool TryDetectRayPack(IReadOnlyDictionary <string, string> buildValues, out BuildInfo buildInfo) { buildInfo = null; if (buildValues == null || !buildValues.Any()) { // Detect RayPack by taking a look at the metadata of PsfLauncher. // This is a fallback in case there are no other build values. const string fileLauncher = "PsfLauncher.exe"; if (!fileReader.FileExists(fileLauncher)) { return(false); } using (var launcher = this.fileReader.GetFile(fileLauncher)) { FileVersionInfo fileVersionInfo; if (launcher is FileStream fileStream) { fileVersionInfo = FileVersionInfo.GetVersionInfo(fileStream.Name); } else { var tempFilePath = Path.GetTempFileName(); try { using (var fs = File.OpenWrite(tempFilePath)) { launcher.CopyTo(fs); fs.Flush(); } fileVersionInfo = FileVersionInfo.GetVersionInfo(tempFilePath); } finally { File.Delete(tempFilePath); } } if (fileVersionInfo.ProductName != null && fileVersionInfo.ProductName.StartsWith("Raynet", StringComparison.OrdinalIgnoreCase)) { var pv = fileVersionInfo.ProductVersion; buildInfo = new BuildInfo { ProductName = "RayPack " + Version.Parse(pv).ToString(2), ProductVersion = fileVersionInfo.ProductVersion }; return(true); } } } else { // Detect RayPack 6.2 which uses build meta data like this: // <build:Item Name="OperatingSystem" Version="6.2.9200.0" /><build:Item Name="Raynet.RaySuite.Common.Appx" Version="6.2.5306.1168" /></build:Metadata> if (!buildValues.TryGetValue("Raynet.RaySuite.Common.Appx", out var rayPack)) { return(false); } if (Version.TryParse(rayPack, out var parsedVersion)) { buildInfo = new BuildInfo { ProductName = $"RayPack {parsedVersion.Major}.{parsedVersion.Minor}", ProductVersion = $"(MSIX builder v{parsedVersion})" }; } else { buildInfo = new BuildInfo { ProductName = "RayPack", ProductVersion = $"(MSIX builder v{rayPack})" }; } if (buildValues.TryGetValue("OperatingSystem", out var os)) { var win10Version = Windows10Parser.GetOperatingSystemFromNameAndVersion(os); buildInfo.OperatingSystem = win10Version.ToString(); } return(true); } return(false); }
public PsfApplicationDescriptor Read(string applicationId, string originalEntryPoint, IAppxFileReader fileReader) { if ( string.Equals(originalEntryPoint, @"AI_STUBS\AiStub.exe", StringComparison.OrdinalIgnoreCase) || string.Equals(originalEntryPoint, @"AI_STUBS\AiStubElevated.exe", StringComparison.OrdinalIgnoreCase)) { if (fileReader.FileExists(@"AI_STUBS\AiStub.exe") || fileReader.FileExists(@"AI_STUBS\AiStubElevated.exe")) { // This is an old Advanced Installer stuff if (fileReader.FileExists("Registry.dat")) { RegistryHiveOnDemand reg; using (var stream = fileReader.GetFile("Registry.dat")) { if (stream is FileStream fileStream) { reg = new RegistryHiveOnDemand(fileStream.Name); } else { using var memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); memoryStream.Flush(); reg = new RegistryHiveOnDemand(memoryStream.ToArray(), "Registry.dat"); } } var key = reg.GetKey(@"root\registry\machine\software\caphyon\advanced installer\" + applicationId); if (key?.Values != null) { var psfDef = new PsfApplicationDescriptor(); foreach (var item in key.Values.Where(item => item.ValueName != null)) { switch (item.ValueName.ToLowerInvariant()) { case "path": psfDef.Executable = (item.ValueData ?? string.Empty).Replace("[{AppVPackageRoot}]\\", string.Empty); break; case "pathai": psfDef.Executable = (item.ValueData ?? string.Empty).Replace("[{AppVPackageRoot}]\\", string.Empty); break; case "workingdirectory": psfDef.WorkingDirectory = (item.ValueData ?? string.Empty).Replace("[{AppVPackageRoot}]\\", string.Empty); break; case "workingdirectoryai": psfDef.WorkingDirectory = (item.ValueData ?? string.Empty).Replace("[{AppVPackageRoot}]\\", string.Empty); break; case "args": psfDef.Arguments = item.ValueData; break; } } if (string.IsNullOrWhiteSpace(psfDef.Executable)) { psfDef.Executable = null; } else if (psfDef.Executable.StartsWith("[{", StringComparison.OrdinalIgnoreCase)) { var indexOfClosing = psfDef.Executable.IndexOf("}]", StringComparison.OrdinalIgnoreCase); if (indexOfClosing != -1) { var middlePart = psfDef.Executable.Substring(2, indexOfClosing - 2); var testedPath = "VFS\\" + middlePart + psfDef.Executable.Substring(indexOfClosing + 2); if (fileReader.FileExists(testedPath)) { // this is to make sure that a path like [{ProgramFilesX86}]\test is replaced to VFS\ProgramFilesX86\test if present psfDef.Executable = testedPath; } } } if (string.IsNullOrWhiteSpace(psfDef.WorkingDirectory)) { psfDef.WorkingDirectory = null; } if (string.IsNullOrWhiteSpace(psfDef.Arguments)) { psfDef.Arguments = null; } return(psfDef); } } } } var dir = Path.GetDirectoryName(originalEntryPoint); string configJson; if (string.IsNullOrEmpty(dir)) { configJson = "config.json"; } else { configJson = Path.Combine(dir, "config.json"); } if (fileReader.FileExists(configJson)) { using (var stream = fileReader.GetFile(configJson)) { using (var streamReader = new StreamReader(stream)) { return(this.Read(applicationId, originalEntryPoint, streamReader)); } } } return(null); }
private static async Task <AppxPackage> Translate(IAppxFileReader fileReader, AppxPackage package, CancellationToken cancellationToken) { var translationRequired = package.DisplayName?.StartsWith("ms-resource:") == true || package.PublisherDisplayName?.StartsWith("ms-resource:") == true || package.Description?.StartsWith("ms-resource:") == true || package.Applications.Any(a => a.DisplayName?.StartsWith("ms-resource:") == true) || package.Applications.Any(a => a.Description?.StartsWith("ms-resource:") == true); if (!translationRequired) { return(package); } string priFullPath = null; var cleanup = false; try { if (fileReader.FileExists("resources.pri")) { using (var stream = fileReader.GetFile("resources.pri")) { if (stream is FileStream fileStream) { priFullPath = fileStream.Name; } else { priFullPath = Path.GetTempFileName(); cleanup = true; using (var fs = File.OpenWrite(priFullPath)) { await stream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); await fs.FlushAsync(cancellationToken).ConfigureAwait(false); } } } package.DisplayName = StringLocalizer.Localize(priFullPath, package.Name, package.FullName, package.DisplayName); package.Description = StringLocalizer.Localize(priFullPath, package.Name, package.FullName, package.Description); package.PublisherDisplayName = StringLocalizer.Localize(priFullPath, package.Name, package.FullName, package.PublisherDisplayName); if (string.IsNullOrEmpty(package.DisplayName)) { package.DisplayName = package.Name; } if (string.IsNullOrEmpty(package.PublisherDisplayName)) { package.PublisherDisplayName = package.Publisher; } foreach (var app in package.Applications ?? Enumerable.Empty <AppxApplication>()) { app.DisplayName = StringLocalizer.Localize(priFullPath, app.Id, package.FullName, app.DisplayName); if (string.IsNullOrEmpty(app.DisplayName)) { app.DisplayName = app.Id; } app.Description = StringLocalizer.Localize(priFullPath, app.Id, package.FullName, app.Description); } } return(package); } finally { if (cleanup && File.Exists(priFullPath)) { File.Delete(priFullPath); } } }