private static AppxManifest GetManifestInformationForAppxPackage(IStream stream) { var appxManifest = new AppxManifest(); try { var appxFactory = (IAppxFactory) new AppxFactory(); var appxPackageReader = appxFactory.CreatePackageReader(stream); var appxManifestReader = appxPackageReader.GetManifest(); appxManifest.Name = appxManifestReader.GetPackageId().GetName(); appxManifest.Version = appxManifestReader.GetPackageId().GetVersion(); appxManifest.Publisher = appxManifestReader.GetPackageId().GetPublisher(); appxManifest.ResourceID = appxManifestReader.GetPackageId().GetResourceId(); appxManifest.ProcessorArchitecture = appxManifestReader.GetPackageId().GetArchitecture(); Marshal.ReleaseComObject(appxManifestReader); Marshal.ReleaseComObject(appxPackageReader); Marshal.ReleaseComObject(appxFactory); } catch { // TBD } return(appxManifest); }
public AppxPackage() { BlockMap = new Dictionary <string, List <AppxBlockMapFile> >(); Manifest = new AppxManifest(); ParentPackage = null; PackageType = PACKAGE_TYPE.PACKAGE_TYPE_APPX_PACKAGE; UncompressedSize = 0; PackageFileName = string.Empty; }
public bool IsUpdate(AppxManifest incomming, out string errorMsg) { errorMsg = string.Empty; // different name if (this.Name.CompareTo(incomming.Name) != 0) { errorMsg = "Packages have a different Name."; return(false); } // different publisher if (this.Publisher.CompareTo(incomming.Publisher) != 0) { errorMsg = "Packages have a different Publisher."; return(false); } // different resource ID if (this.ResourceID != null && incomming.ResourceID != null && this.ResourceID.CompareTo(incomming.ResourceID) != 0) { errorMsg = "Packages have a different ResourceID."; return(false); } // this is x86 or x64 and that is arm or arm64 if ((this.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_X64 || this.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_X86) && incomming.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_ARM || incomming.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_ARM64) { errorMsg = "Packages have incompatible architectures."; return(false); } // this is arm or arm64 and that is x86 or x64 if ((this.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_ARM || this.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_ARM64) && incomming.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_X64 || incomming.ProcessorArchitecture == APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_X86) { errorMsg = "Packages have incompatible architectures."; return(false); } // same version package if (ComparePackageVersions(incomming) == 0) { errorMsg = "Packages are the same version."; return(false); } return(true); }
private void Analyze_Async_Update(object state) { AppxPackageComparisonResult result = new AppxPackageComparisonResult(); try { List <string> packagePaths = state as List <string>; // make sure there are only two packages if (packagePaths.Count > 2) { ShowError("Too many packages", "There can only be 2 packages selected for an update check."); return; } else if (packagePaths.Count < 2) { ShowError("Too few packages", "There must be 2 packages selected for an update check."); return; } string firstPackagePath = packagePaths[0]; string secondPackagePath = packagePaths[1]; // make sure they're both the same package type if (0 != Path.GetExtension(firstPackagePath).ToLower() .CompareTo( Path.GetExtension(secondPackagePath).ToLower())) { ShowError("Different Package Types", "The packages must be of the same type (e.g. both .appxbundle or both .appx)"); return; } AppxManifest firstPackageManifest = AppxPackageReader.GetManifestFromPath(firstPackagePath); AppxManifest secondPackageManifest = AppxPackageReader.GetManifestFromPath(secondPackagePath); string errorMsg; if (!firstPackageManifest.IsUpdate(secondPackageManifest, out errorMsg)) { ShowError("Identities not suited for update", errorMsg); return; } AppxPackageReader incommingPackageReader; AppxPackageReader outgoingpackageReader; // firstPackageManifest is incomming (newer) if (firstPackageManifest.ComparePackageVersions(secondPackageManifest) > 0) { incommingPackageReader = new AppxPackageReader(firstPackagePath); outgoingpackageReader = new AppxPackageReader(secondPackagePath); } // secondPackageManifest is incomming (newer) else { outgoingpackageReader = new AppxPackageReader(firstPackagePath); incommingPackageReader = new AppxPackageReader(secondPackagePath); } // read the packages incommingPackageReader.Run(); outgoingpackageReader.Run(); // get all the packages List <AppxPackage> incommingPackageSet = new List <AppxPackage>(); List <AppxPackage> outgoingPackageSet = new List <AppxPackage>(); incommingPackageReader.Wait(); incommingPackageSet.AddRange(incommingPackageReader.MainPackages); incommingPackageSet.AddRange(incommingPackageReader.ResourcePackages); outgoingpackageReader.Wait(); outgoingPackageSet.AddRange(outgoingpackageReader.MainPackages); outgoingPackageSet.AddRange(outgoingpackageReader.ResourcePackages); // get the list of block map files Dictionary <string, List <AppxBlockMapFile> > incommingPackageFiles = new Dictionary <string, List <AppxBlockMapFile> >(); foreach (AppxPackage p in incommingPackageSet) { incommingPackageFiles = incommingPackageFiles.Concat(p.BlockMap) .GroupBy(kvp => kvp.Key) .ToDictionary(g => g.Key, g => g.SelectMany(v => v.Value).ToList()); } Dictionary <string, List <AppxBlockMapFile> > outgoingPackageFiles = new Dictionary <string, List <AppxBlockMapFile> >(); foreach (AppxPackage p in outgoingPackageSet) { outgoingPackageFiles = outgoingPackageFiles.Concat(p.BlockMap) .GroupBy(kvp => kvp.Key) .ToDictionary(g => g.Key, g => g.SelectMany(v => v.Value).ToList()); } // Determine the hardlinked files List <string> sameFileHashes = new List <string>(); foreach (string key in incommingPackageFiles.Keys) { // if it's the same if (outgoingPackageFiles.ContainsKey(key)) { sameFileHashes.Add(key); foreach (AppxBlockMapFile a in incommingPackageFiles[key]) { result.BytesHardlinked += a.UncompressedSize; } ChangeResult cr = new ChangeResult() { Package = incommingPackageFiles[key].First().ParentPackage.Manifest.FullName(), FileName = incommingPackageFiles[key].First().FileName, BlockHash = incommingPackageFiles[key].First().FinalFileHash, Size = incommingPackageFiles[key].First().UncompressedSize, }; result.FileHardLinkChangeResults.Add(cr.FileName, cr); } } // remove hardlinked files foreach (string key in sameFileHashes) { incommingPackageFiles.Remove(key); outgoingPackageFiles.Remove(key); } //get full list of blocks Dictionary <string, List <AppxBlockMapBlock> > incommingPackageBlocks = new Dictionary <string, List <AppxBlockMapBlock> >(); Dictionary <string, List <AppxBlockMapBlock> > outgoingPackageBlocks = new Dictionary <string, List <AppxBlockMapBlock> >(); foreach (List <AppxBlockMapFile> list in incommingPackageFiles.Values) { foreach (AppxBlockMapFile file in list) { foreach (AppxBlockMapBlock block in file.Blocks) { if (!incommingPackageBlocks.ContainsKey(block.Hash)) { incommingPackageBlocks.Add(block.Hash, new List <AppxBlockMapBlock>()); } incommingPackageBlocks[block.Hash].Add(block); } } } foreach (List <AppxBlockMapFile> list in outgoingPackageFiles.Values) { foreach (AppxBlockMapFile file in list) { foreach (AppxBlockMapBlock block in file.Blocks) { if (!outgoingPackageBlocks.ContainsKey(block.Hash)) { outgoingPackageBlocks.Add(block.Hash, new List <AppxBlockMapBlock>()); } outgoingPackageBlocks[block.Hash].Add(block); } } } // Determine Copied / Downloaded foreach (string hash in incommingPackageBlocks.Keys) { // if its going to be copied if (outgoingPackageBlocks.ContainsKey(hash)) { result.BlocksCopied += incommingPackageBlocks[hash].First().CompressedSize *(ulong)incommingPackageBlocks[hash].Count; ChangeResult cr = new ChangeResult() { Package = incommingPackageBlocks[hash].First().ParentFile.ParentPackage.Manifest.FullName(), FileName = incommingPackageBlocks[hash].First().ParentFile.FileName, BlockHash = incommingPackageBlocks[hash].First().Hash, Size = incommingPackageBlocks[hash].First().ParentFile.UncompressedSize, }; if (!result.BlockCopiedChangeResults.ContainsKey(cr.FileName)) { result.BlockCopiedChangeResults.Add(cr.FileName, cr); } } // if its going to be downloaded else if (!outgoingPackageBlocks.ContainsKey(hash)) { result.BlocksDownloaded += incommingPackageBlocks[hash].First().CompressedSize *(ulong)incommingPackageBlocks[hash].Count; ChangeResult cr = new ChangeResult() { Package = incommingPackageBlocks[hash].First().ParentFile.ParentPackage.Manifest.FullName(), FileName = incommingPackageBlocks[hash].First().ParentFile.FileName, BlockHash = incommingPackageBlocks[hash].First().Hash, Size = incommingPackageBlocks[hash].First().ParentFile.UncompressedSize, }; if (!result.BlockDownloadChangeResults.ContainsKey(cr.FileName)) { result.BlockDownloadChangeResults.Add(cr.FileName, cr); } } } foreach (string hash in outgoingPackageBlocks.Keys) { // if its going to be deleted if (!incommingPackageBlocks.ContainsKey(hash)) { result.BlocksDeleted += outgoingPackageBlocks[hash].First().CompressedSize *(ulong)outgoingPackageBlocks[hash].Count; ChangeResult cr = new ChangeResult() { Package = outgoingPackageBlocks[hash].First().ParentFile.ParentPackage.Manifest.FullName(), FileName = outgoingPackageBlocks[hash].First().ParentFile.FileName, BlockHash = outgoingPackageBlocks[hash].First().Hash, Size = outgoingPackageBlocks[hash].First().ParentFile.UncompressedSize, }; if (!result.BlockDeletedChangeResults.ContainsKey(cr.FileName)) { result.BlockDeletedChangeResults.Add(cr.FileName, cr); } } } } catch (Exception ex) { } this.Dispatcher.BeginInvoke(new OutputUpdateComparisonDataToUIDelegate(OutputUpdateComparisonDataToUI), result); }
// return // -1 if other package is newer // 0 if they are the same version // 1 if this package is newer public int ComparePackageVersions(AppxManifest incomming) { return(Version.CompareTo(incomming.Version)); }