예제 #1
0
        public static void ImportAppxBundles()
        {
            AppXBundleList = new List<AppXBundle>();

            string importPath = HttpContext.Current.Server.MapPath("~/App_Data/AppX-Import");
            string storePath = HttpContext.Current.Server.MapPath("~/App_Data/AppXBundle-Store");

            DirectoryInfo importDir = new DirectoryInfo(importPath);

            FileInfo[] bundles = importDir.GetFiles("*.appxbundle");

            foreach (FileInfo bundle in bundles)
            {
                ZipArchive za = ZipFile.OpenRead(bundle.FullName);
                var bundleManifest = za.Entries.First(f => f.FullName == "AppxMetadata/AppxBundleManifest.xml");
                string xmlPath = Path.Combine(importPath, bundle.Name.Substring(0, bundle.Name.Length - bundle.Extension.Length) + ".xml");

                if (!File.Exists(xmlPath))
                {
                    bundleManifest.ExtractToFile(xmlPath);
                }

                za.Dispose();
                FileStream bundleManifestStr = new FileStream(xmlPath, FileMode.Open);
                XDocument bundleManifestXml = XDocument.Load(bundleManifestStr);

                SHA256 hash = SHA256.Create();
                FileStream bundleStr = bundle.OpenRead();
                byte[] hashBytes = hash.ComputeHash(bundleStr);
                bundleStr.Close();
                bundleStr.Dispose();

                StringBuilder hashString = new StringBuilder();

                for (int i = 0; i < hashBytes.Length; i++)
                {
                    hashString.Append(hashBytes[i].ToString("X2"));
                }

                try
                {
                    AppXBundle item = new AppXBundle()
                    {
                        AppxBundleId = Guid.NewGuid(),

                        Size = bundle.Length,
                        Sha256Hash = hashString.ToString(),

                        Name = bundleManifestXml.Root.LocalElement("Identity").Attribute("Name").Value,
                        Version = Version.Parse(bundleManifestXml.Root.LocalElement("Identity").Attribute("Version").Value),
                        Publisher = bundleManifestXml.Root.LocalElement("Identity").Attribute("Publisher").Value
                    };

                    bundleManifestStr.Close();

                    File.Delete(xmlPath);

                    // Import and Store details
                    DirectoryInfo storeDir = Directory.CreateDirectory(Path.Combine(storePath, item.AppxBundleId.ToString()));
                    File.Move(bundle.FullName, Path.Combine(storeDir.FullName, bundle.Name));

                    item.Path = Path.Combine(storeDir.FullName, bundle.Name).Substring(storePath.Length + 1);
                    FileStream fStr = new FileStream(Path.Combine(storeDir.FullName, "data.bin"), FileMode.CreateNew);

                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(fStr, item);

                    fStr.Flush();
                    fStr.Close();

                    ImportPackagesFromBundle(item, storeDir);
                }
                catch (Exception e)
                {
                    Error elmahErr = new Error(e, HttpContext.Current);
                    elmahErr.ServerVariables.Add("Bundle Path", bundle.FullName);
                    ErrorLog.GetDefault(HttpContext.Current).Log(elmahErr);

                    bundleManifestStr.Close();

                    File.Delete(xmlPath);
                    continue;
                }
            }

            foreach (DirectoryInfo storedAppx in new DirectoryInfo(storePath).GetDirectories())
            {
                FileInfo storeBin = new FileInfo(Path.Combine(storedAppx.FullName, "data.bin"));

                FileStream storeBinStr = storeBin.OpenRead();
                BinaryFormatter bf = new BinaryFormatter();
                AppXBundle item = bf.Deserialize(storeBinStr) as AppXBundle;

                if (item != null)
                {
                    if (AppXBundleList.SingleOrDefault(a => a.Sha256Hash == item.Sha256Hash) != null)
                    {
                        Error elmahErr = new Error(new Exception("Duplicate AppXBundle"));
                        elmahErr.ServerVariables.Add("AppXBundle Path 1", AppXBundleList.SingleOrDefault(a => a.Sha256Hash == item.Sha256Hash).Path);
                        elmahErr.ServerVariables.Add("AppXBundle Path 2", item.Path);

                        ErrorLog.GetDefault(HttpContext.Current).Log(elmahErr);
                    }
                    else
                    {
                        item.Packages = new List<AppXFromBundle>();
                        FileInfo[] packageBins = storedAppx.GetDirectories("Packages").First().GetFiles("*.bin");
                        foreach (FileInfo packageBin in packageBins)
                        {
                            FileStream packageBinStr = packageBin.OpenRead();
                            AppXFromBundle package = bf.Deserialize(packageBinStr) as AppXFromBundle;
                            item.Packages.Add(package);
                            packageBinStr.Close();
                        }
                        AppXBundleList.Add(item);
                    }
                }

                storeBinStr.Close();
            }
        }
예제 #2
0
        private static void ImportPackagesFromBundle(AppXBundle item, DirectoryInfo storeDir)
        {
            // time to bring out the packages
            ZipArchive za = ZipFile.OpenRead(Path.Combine(storeDir.Parent.FullName, item.Path));
            DirectoryInfo packagesDir = Directory.CreateDirectory(Path.Combine(storeDir.FullName, "Packages"));

            var packages = za.Entries.Where(f => f.Name.EndsWith(".appx"));
            foreach (var package in packages)
            {
                package.ExtractToFile(Path.Combine(packagesDir.FullName, package.Name));
            }

            za.Dispose();

            FileInfo[] packageInfos = packagesDir.GetFiles("*.appx");

            foreach (FileInfo package in packageInfos)
            {
                ZipArchive pza = ZipFile.OpenRead(package.FullName);
                var appxManifest = pza.Entries.First(f => f.Name == "AppxManifest.xml");
                string xmlPath = Path.Combine(packagesDir.FullName, package.Name.Substring(0, package.Name.Length - package.Extension.Length) + ".xml");

                if (!File.Exists(xmlPath))
                {
                    appxManifest.ExtractToFile(xmlPath);
                }

                pza.Dispose();
                FileStream appxManifestStr = new FileStream(xmlPath, FileMode.Open);
                XDocument appxManifestXml = XDocument.Load(appxManifestStr);

                SHA256 hash = SHA256.Create();
                FileStream appxStr = package.OpenRead();
                byte[] hashBytes = hash.ComputeHash(appxStr);
                appxStr.Close();
                appxStr.Dispose();

                StringBuilder hashString = new StringBuilder();

                for (int i = 0; i < hashBytes.Length; i++)
                {
                    hashString.Append(hashBytes[i].ToString("X2"));
                }

                try
                {
                    AppXFromBundle packageItem = new AppXFromBundle()
                    {
                        AppxId = Guid.NewGuid(),

                        Size = package.Length,
                        Sha256Hash = hashString.ToString(),

                        Name = appxManifestXml.Root.LocalElement("Identity").Attribute("Name").Value,
                        Version = Version.Parse(appxManifestXml.Root.LocalElement("Identity").Attribute("Version").Value),
                        Publisher = appxManifestXml.Root.LocalElement("Identity").Attribute("Publisher").Value,
                        ProcessorArchitecture = (Architecture)Enum.Parse(typeof(Architecture), appxManifestXml.Root.LocalElement("Identity").Attribute("ProcessorArchitecture") == null ? "neutral" : appxManifestXml.Root.LocalElement("Identity").Attribute("ProcessorArchitecture").Value),

                        DisplayName = appxManifestXml.Root.LocalElement("Properties").LocalElement("DisplayName").Value,
                        Description = appxManifestXml.Root.LocalElement("Properties").LocalElement("Description") != null ? appxManifestXml.Root.LocalElement("Properties").LocalElement("Description").Value : "",
                        PublisherDisplayName = appxManifestXml.Root.LocalElement("Properties").LocalElement("PublisherDisplayName").Value,

                        OSMinVersion = Version.Parse(appxManifestXml.Root.LocalElement("Prerequisites").LocalElement("OSMinVersion").Value),
                        OSMaxVersionTested = Version.Parse(appxManifestXml.Root.LocalElement("Prerequisites").LocalElement("OSMaxVersionTested").Value),

                        IsResourcePackage = appxManifestXml.Root.LocalElement("Properties").LocalElement("ResourcePackage") != null ? bool.Parse(appxManifestXml.Root.LocalElement("Properties").LocalElement("ResourcePackage").Value) : false,
                        ResourceId = appxManifestXml.Root.LocalElement("Identity").Attribute("ResourceId") != null ? appxManifestXml.Root.LocalElement("Identity").Attribute("ResourceId").Value : "",
                        ResourcesProvided = (from res in appxManifestXml.Root.LocalElement("Identity").Elements()
                                            where res.Name.LocalName == "Resource"
                                            select new
                                            {
                                                resourceType = res.Attributes().First().Name.LocalName,
                                                resourceValue = res.Attributes().First().Value
                                            }).ToDictionary(o => o.resourceType, o => o.resourceValue)
                    };
                    appxManifestStr.Close();

                    File.Delete(xmlPath);

                    // Import and Store details
                    packageItem.Path = Path.Combine(storeDir.FullName, "Packages", package.Name).Substring(storeDir.Parent.FullName.Length + 1);
                    FileStream fStr = new FileStream(Path.Combine(packagesDir.FullName, string.Format("{0}.bin", package.Name.Substring(0, package.Name.Length - package.Extension.Length))), FileMode.CreateNew);

                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(fStr, packageItem);

                    fStr.Flush();
                    fStr.Close();
                }
                catch (Exception e)
                {
                    Error elmahErr = new Error(e, HttpContext.Current);
                    elmahErr.ServerVariables.Add("AppX Path", package.FullName);
                    ErrorLog.GetDefault(HttpContext.Current).Log(elmahErr);

                    appxManifestStr.Close();

                    File.Delete(xmlPath);
                    continue;
                }
            }
        }