Example #1
0
        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;
 }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
 // 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));
 }