diff --git a/AppxPackage/AppxPackage.csproj b/AppxPackage/AppxPackage.csproj
index f1694e0..3941460 100644
--- a/AppxPackage/AppxPackage.csproj
+++ b/AppxPackage/AppxPackage.csproj
@@ -48,6 +48,10 @@
MinimumRecommendedRules.ruleset
+
+ ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll
+ True
+
..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll
True
@@ -70,6 +74,7 @@
+
diff --git a/AppxPackage/PackageReader.cs b/AppxPackage/PackageReader.cs
index f6bb9c3..a06c2f5 100644
--- a/AppxPackage/PackageReader.cs
+++ b/AppxPackage/PackageReader.cs
@@ -5,8 +5,14 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
+using System.Dynamic;
using AppxPackage.Info;
using NativeWrappers;
+using System.Threading.Tasks;
+using ICSharpCode.SharpZipLib;
+using System.IO;
+using System.Xml;
+using ICSharpCode.SharpZipLib.Zip;
//using PriFormat;
namespace AppxPackage
{
@@ -88,6 +94,305 @@ namespace AppxPackage
return ret;
}
}
+ internal class PriAllValuesReader: IDisposable
+ {
+ public PackageReader pr = null;
+ private Dictionary pkgAppDict = new Dictionary ();
+ private Dictionary pkgLocDict = new Dictionary ();
+ private Dictionary pkgScaDict = new Dictionary ();
+ private Dictionary priAppPkg = new Dictionary ();
+ private Dictionary priLocPkg = new Dictionary ();
+ private Dictionary priScaPkg = new Dictionary ();
+ public PriAllValuesReader (PackageReader p_pr)
+ {
+ pr = p_pr;
+ }
+ public void Init ()
+ {
+ var hPkg = pr.Instance;
+ var pkgType = pr.Type;
+ if (pkgType == PackageType.Appx)
+ {
+ var priinst = PackageReadHelper.GetAppxFileFromAppxPackage (hPkg, "resources.pri");
+ pkgAppDict [IntPtr.Zero] = priinst;
+ priAppPkg [priinst] = (new PriReader (priinst));
+ }
+ else if (pkgType == PackageType.Bundle)
+ {
+ var appPkg = PackageReadHelper.GetAppxBundleApplicationPackageFile (hPkg);
+ var appPkgPri = PackageReadHelper.GetFileFromPayloadPackage (appPkg, "resources.pri");
+ pkgAppDict [appPkg] = appPkgPri;
+ priAppPkg [appPkgPri] = new PriReader (appPkgPri);
+ var localeResPkgList = PackageReadHelper.GetAppxBundleAllLocaleResourcePackageFileNameList (hPkg);
+ foreach (var filename in localeResPkgList)
+ {
+ var localePkg = PackageReadHelper.GetAppxBundlePayloadPackageFile (hPkg, filename);
+ var localePkgPri = PackageReadHelper.GetFileFromPayloadPackage (localePkg, "resources.pri");
+ pkgLocDict [localePkg] = localePkgPri;
+ priLocPkg [localePkg] = (new PriReader (localePkgPri));
+ }
+ var fileResPkgList = PackageReadHelper.GetAppxBundleAllFileResourcePackageFileNameList (hPkg);
+ foreach (var filename in fileResPkgList)
+ {
+ var filePkg = PackageReadHelper.GetAppxBundlePayloadPackageFile (hPkg, filename);
+ var filePkgPri = PackageReadHelper.GetFileFromPayloadPackage (filePkg, "resources.pri");
+ pkgScaDict [filePkg] = filePkgPri;
+ priScaPkg [filePkgPri] = (new PriReader (filePkgPri));
+ }
+ }
+ }
+ public void Dispose ()
+ {
+ if (pr == null) return;
+ foreach (var i in priAppPkg) if (i.Value != null) i.Value.Dispose ();
+ foreach (var i in priLocPkg) if (i.Value != null) i.Value.Dispose ();
+ foreach (var i in priScaPkg) if (i.Value != null) i.Value.Dispose ();
+ priAppPkg.Clear ();
+ priLocPkg.Clear ();
+ priScaPkg.Clear ();
+ priAppPkg = null;
+ priLocPkg = null;
+ priScaPkg = null;
+ foreach (var kv in pkgAppDict)
+ {
+ if (kv.Value != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (kv.Value);
+ if (kv.Key != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (kv.Key);
+ }
+ foreach (var kv in pkgLocDict)
+ {
+ if (kv.Value != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (kv.Value);
+ if (kv.Key != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (kv.Key);
+ }
+ foreach (var kv in pkgScaDict)
+ {
+ if (kv.Value != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (kv.Value);
+ if (kv.Key != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (kv.Key);
+ }
+ pkgAppDict.Clear ();
+ pkgLocDict.Clear ();
+ pkgScaDict.Clear ();
+ pkgAppDict = null;
+ pkgLocDict = null;
+ pkgScaDict = null;
+ pr = null;
+ }
+ ///
+ /// 获取某个本地化字符串资源的所有语言资源
+ ///
+ /// 资源 ID,一般为“ms-resource:”开头
+ /// 返回以区域代码为键,本地化字符串为值的字典
+ public Dictionary LocaleResourceAllValues (string resid)
+ {
+ var dict = new Dictionary (StringComparer.OrdinalIgnoreCase);
+ foreach (var pri in priAppPkg)
+ {
+ foreach (var kv in pri.Value.LocaleResourceAllValue (resid))
+ {
+ dict [kv.Key] = kv.Value;
+ }
+ }
+ foreach (var pri in priLocPkg)
+ {
+ foreach (var kv in pri.Value.LocaleResourceAllValue (resid))
+ {
+ dict [kv.Key] = kv.Value;
+ }
+ }
+ return dict;
+ }
+ ///
+ /// 获取某个涉及缩放资源的文件名及其文件的 Base64。
+ ///
+ /// 资源 ID,一般为文件名,如“Assert\LargeTile.png”
+ /// 返回以缩放比和高对比度为键,一个前者为文件名,后者为 data url 组成的元组为值的字典
+ public Dictionary> FileResourceAllValues (string resid)
+ {
+ var dict = new Dictionary> ();
+ var rePkgDict = new Dictionary ();
+ foreach (var kv in pkgAppDict)
+ rePkgDict [kv.Value] = kv.Key;
+ foreach (var pri in priAppPkg)
+ {
+ var pkg = rePkgDict [pri.Key];
+ #region appx
+ if (pr.Type == PackageType.Appx)
+ {
+ foreach (var kv in pri.Value.PathResourceAllValue (resid))
+ {
+ var imgInst = PackageReadHelper.GetAppxFileFromAppxPackage (pr.Instance, kv.Value);
+ IntPtr b64ph;
+ var b64p = PackageReadHelper.StreamToBase64W (imgInst, null, 0, out b64ph);
+ var imgB64 = "";
+ if (b64p != IntPtr.Zero) imgB64 = Marshal.PtrToStringUni (b64p);
+ if (b64p != IntPtr.Zero) PackageReadHelper.PackageReaderFreeString (b64p);
+ dict [kv.Key] = new Tuple (kv.Value, imgB64);
+ }
+ }
+ #endregion
+ #region bundle
+ else if (pr.Type == PackageType.Bundle)
+ {
+ foreach (var kv in pri.Value.PathResourceAllValue (resid))
+ {
+ var imgInst = PackageReadHelper.GetFileFromPayloadPackage (pkg, kv.Value);
+ IntPtr b64ph;
+ var b64p = PackageReadHelper.StreamToBase64W (imgInst, null, 0, out b64ph);
+ var imgB64 = "";
+ if (b64p != IntPtr.Zero) imgB64 = Marshal.PtrToStringUni (b64p);
+ if (b64p != IntPtr.Zero) PackageReadHelper.PackageReaderFreeString (b64p);
+ dict [kv.Key] = new Tuple (kv.Value, imgB64);
+ }
+ }
+ #endregion
+ }
+ rePkgDict.Clear ();
+ foreach (var kv in pkgScaDict) rePkgDict [kv.Value] = kv.Key;
+ foreach (var pri in priScaPkg)
+ {
+ var pkg = rePkgDict [pri.Key];
+ foreach (var kv in pri.Value.PathResourceAllValue (resid))
+ {
+ var imgInst = PackageReadHelper.GetFileFromPayloadPackage (pkg, kv.Value);
+ IntPtr b64ph;
+ var b64p = PackageReadHelper.StreamToBase64W (imgInst, null, 0, out b64ph);
+ var imgB64 = "";
+ if (b64p != IntPtr.Zero) imgB64 = Marshal.PtrToStringUni (b64p);
+ if (b64p != IntPtr.Zero) PackageReadHelper.PackageReaderFreeString (b64p);
+ dict [kv.Key] = new Tuple (kv.Value, imgB64);
+ }
+ }
+ return dict;
+ }
+ private static byte [] Base64ToBytes (string base64)
+ {
+ int commaIndex = base64.IndexOf (',');
+ if (commaIndex >= 0)
+ {
+ base64 = base64.Substring (commaIndex + 1);
+ }
+ try
+ {
+ return Convert.FromBase64String (base64);
+ }
+ catch
+ {
+ return new byte [0];
+ }
+ }
+ internal class TrimIgnoreCaseComparer: IEqualityComparer
+ {
+ public bool Equals (string x, string y)
+ {
+ if (x == null && y == null) return true;
+ if (x == null || y == null) return false;
+ return string.Equals (x.Trim (), y.Trim (), StringComparison.OrdinalIgnoreCase);
+ }
+ public int GetHashCode (string obj)
+ {
+ if (obj == null) return 0;
+ return obj.Trim ().ToLowerInvariant ().GetHashCode ();
+ }
+ }
+ private HashSet set = new HashSet (new TrimIgnoreCaseComparer ());
+ public Dictionary FileResourceAllValues (string resid, ZipOutputStream zos)
+ {
+ var comparer = new TrimIgnoreCaseComparer ();
+ var dict = new Dictionary ();
+ var rePkgDict = new Dictionary ();
+ foreach (var kv in pkgAppDict)
+ rePkgDict [kv.Value] = kv.Key;
+ foreach (var pri in priAppPkg)
+ {
+ var pkg = rePkgDict [pri.Key];
+ #region appx
+ if (pr.Type == PackageType.Appx)
+ {
+ foreach (var kv in pri.Value.PathResourceAllValue (resid))
+ {
+ dict [kv.Key] = kv.Value;
+ if (set.Contains (kv.Value, comparer)) continue;
+ else set.Add (kv.Value);
+ var imgInst = PackageReadHelper.GetAppxFileFromAppxPackage (pr.Instance, kv.Value);
+ IntPtr b64ph;
+ var b64p = PackageReadHelper.StreamToBase64W (imgInst, null, 0, out b64ph);
+ var imgB64 = "";
+ if (b64p != IntPtr.Zero) imgB64 = Marshal.PtrToStringUni (b64p);
+ if (b64p != IntPtr.Zero) PackageReadHelper.PackageReaderFreeString (b64p);
+ if (zos != null)
+ {
+ var entryPath = kv.Value.Replace ('\\', '/');
+ var ze = new ZipEntry (entryPath);
+ ze.DateTime = DateTime.Now;
+ zos.PutNextEntry (ze);
+ var bytes = Base64ToBytes (imgB64);
+ zos.Write (bytes, 0, bytes.Length);
+ zos.CloseEntry ();
+ }
+ }
+ }
+ #endregion
+ #region bundle
+ else if (pr.Type == PackageType.Bundle)
+ {
+ foreach (var kv in pri.Value.PathResourceAllValue (resid))
+ {
+ dict [kv.Key] = kv.Value;
+ if (set.Contains (kv.Value, comparer)) continue;
+ else set.Add (kv.Value);
+ var imgInst = PackageReadHelper.GetFileFromPayloadPackage (pkg, kv.Value);
+ IntPtr b64ph;
+ var b64p = PackageReadHelper.StreamToBase64W (imgInst, null, 0, out b64ph);
+ var imgB64 = "";
+ if (b64p != IntPtr.Zero) imgB64 = Marshal.PtrToStringUni (b64p);
+ if (b64p != IntPtr.Zero) PackageReadHelper.PackageReaderFreeString (b64p);
+ if (zos != null)
+ {
+ var ze = new ZipEntry (kv.Value.Replace ('\\', '/'));
+ ze.DateTime = DateTime.Now;
+ zos.PutNextEntry (ze);
+ var bytes = Base64ToBytes (imgB64);
+ zos.Write (bytes, 0, bytes.Length);
+ zos.CloseEntry ();
+ }
+ }
+ }
+ #endregion
+ }
+ rePkgDict.Clear ();
+ foreach (var kv in pkgScaDict) rePkgDict [kv.Value] = kv.Key;
+ foreach (var pri in priScaPkg)
+ {
+ var pkg = rePkgDict [pri.Key];
+ foreach (var kv in pri.Value.PathResourceAllValue (resid))
+ {
+ dict [kv.Key] = kv.Value;
+ if (set.Contains (kv.Value, comparer)) continue;
+ else set.Add (kv.Value);
+ var imgInst = PackageReadHelper.GetFileFromPayloadPackage (pkg, kv.Value);
+ IntPtr b64ph;
+ var b64p = PackageReadHelper.StreamToBase64W (imgInst, null, 0, out b64ph);
+ var imgB64 = "";
+ if (b64p != IntPtr.Zero) imgB64 = Marshal.PtrToStringUni (b64p);
+ if (b64p != IntPtr.Zero) PackageReadHelper.PackageReaderFreeString (b64p);
+ if (zos != null)
+ {
+ var ze = new ZipEntry (kv.Value.Replace ('\\', '/'));
+ ze.DateTime = DateTime.Now;
+ zos.PutNextEntry (ze);
+ var bytes = Base64ToBytes (imgB64);
+ zos.Write (bytes, 0, bytes.Length);
+ zos.CloseEntry ();
+ }
+ }
+ }
+ rePkgDict.Clear ();
+ return dict;
+ }
+ ~PriAllValuesReader ()
+ {
+ set?.Clear ();
+ }
+ }
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]
public class BaseInfoSection: IDisposable, DataUtils.Utilities.IJsonBuild
@@ -192,8 +497,7 @@ namespace AppxPackage
}
public override object BuildJSON ()
{
- return new
- {
+ return new {
name = Name,
package_full_name = FullName,
package_family_name = FamilyName,
@@ -340,12 +644,12 @@ namespace AppxPackage
public bool ResourcePackage { get { return BoolValue ("ResourcePackage"); } }
public override object BuildJSON ()
{
- return new
- {
+ return new {
display_name = DisplayName,
description = Description,
publisher_display_name = Publisher,
Framework = Framework,
+ framework = Framework,
resource_package = ResourcePackage,
logo = Logo,
logo_base64 = LogoBase64
@@ -688,8 +992,7 @@ namespace AppxPackage
{
using (var apps = this)
{
- return apps.Select (app =>
- {
+ return apps.Select (app => {
var dict = new Dictionary (StringComparer.OrdinalIgnoreCase);
foreach (var kv in app)
{
@@ -713,7 +1016,7 @@ namespace AppxPackage
[ClassInterface (ClassInterfaceType.AutoDual)]
public class PRCapabilities: BaseInfoSection, ICapabilities
{
- public PRCapabilities (ref IntPtr hReader) : base (ref hReader) {}
+ public PRCapabilities (ref IntPtr hReader) : base (ref hReader) { }
public List Capabilities
{
get
@@ -791,8 +1094,7 @@ namespace AppxPackage
}
public override object BuildJSON ()
{
- return new
- {
+ return new {
capabilities_name = Capabilities,
device_capabilities = DeviceCapabilities,
display_capabilities_name = CapabilityDisplayNames
@@ -843,8 +1145,7 @@ namespace AppxPackage
}
public override object BuildJSON ()
{
- return this.Select (d => new
- {
+ return this.Select (d => new {
name = d.Name,
publisher = d.Publisher,
vermin = d.Version.BuildJSON ()
@@ -855,7 +1156,7 @@ namespace AppxPackage
[ClassInterface (ClassInterfaceType.AutoDual)]
public class PRResources: BaseInfoSection, IResources
{
- public PRResources (ref IntPtr hReader) : base (ref hReader) {}
+ public PRResources (ref IntPtr hReader) : base (ref hReader) { }
public List DXFeatures
{
get
@@ -873,7 +1174,7 @@ namespace AppxPackage
return ret;
}
}
- public List Languages
+ public List Languages
{
get
{
@@ -932,8 +1233,7 @@ namespace AppxPackage
}
public override object BuildJSON ()
{
- return new
- {
+ return new {
dx_feature_levels = DXFeatures.Select (e => (int)e).ToList (),
languages = Languages,
scales = Scales
@@ -942,7 +1242,7 @@ namespace AppxPackage
}
public class PRPrerequisites: BaseInfoSection, IPrerequisites
{
- public PRPrerequisites (ref IntPtr hReader) : base (ref hReader) {}
+ public PRPrerequisites (ref IntPtr hReader) : base (ref hReader) { }
protected DataUtils.Version GetVersion (string name)
{
PackageReadHelper.VERSION ver;
@@ -961,8 +1261,7 @@ namespace AppxPackage
public string OSMinVersionDescription { get { return GetVersionDescription ("OSMinVersion"); } }
public override object BuildJSON ()
{
- return new
- {
+ return new {
os_min_version = OSMinVersion.BuildJSON (),
os_min_version_description = OSMinVersionDescription,
os_max_version_tested = OSMaxVersionTested.BuildJSON (),
@@ -1002,7 +1301,8 @@ namespace AppxPackage
m_priStreams.Add (istream);
m_priBundle.Set (3, istream);
}
- } break;
+ }
+ break;
case PackageType.Bundle:
{
IntPtr hls = IntPtr.Zero, hss = IntPtr.Zero;
@@ -1055,7 +1355,7 @@ namespace AppxPackage
}
}
}
- finally {}
+ finally { }
}
finally
{
@@ -1064,7 +1364,8 @@ namespace AppxPackage
if (hss != IntPtr.Zero) PackageReadHelper.DestroyAppxFileStream (hss);
IntPtr hlpri = IntPtr.Zero, hspri = IntPtr.Zero;
}
- } break;
+ }
+ break;
}
#endregion
return;
@@ -1152,8 +1453,7 @@ namespace AppxPackage
public void BuildJsonTextAsync (object callback)
{
if (callback == null) return;
- Thread thread = new Thread (() =>
- {
+ Thread thread = new Thread (() => {
string json = string.Empty;
try
{
@@ -1171,8 +1471,7 @@ namespace AppxPackage
}
private object BuildJsonObject ()
{
- return new
- {
+ return new {
valid = IsValid,
filepath = FilePath,
type = (int)Type,
@@ -1188,5 +1487,1038 @@ namespace AppxPackage
}
public static bool AddApplicationItem (string itemName) => PackageReadHelper.AddPackageApplicationItemGetName (itemName);
public static bool RemoveApplicationItem (string itemName) => PackageReadHelper.RemovePackageApplicationItemGetName (itemName);
+ public static string [] GetApplicationItem () => PackageReadHelper.GetApplicationItemNames ();
+ public static void UpdateApplicationItems (IEnumerable items) => PackageReadHelper.SetApplicationItemNames (items);
+ public string BuildJsonForUse ()
+ {
+ bool parsePri = UsePri;
+ bool usePri = EnablePri;
+ try
+ {
+ UsePri = false;
+ EnablePri = false;
+ object packageInfo = null;
+ #region file
+ var typestr = "unknown";
+ switch (Type)
+ {
+ case PackageType.Appx: typestr = "appx"; break;
+ case PackageType.Bundle: typestr = "bundle"; break;
+ default:
+ case PackageType.Unknown: typestr = "unknown"; break;
+ }
+ var rolestr = "unknown";
+ switch (Role)
+ {
+ case PackageRole.Application: rolestr = "application"; break;
+ case PackageRole.Framework: rolestr = "framework"; break;
+ case PackageRole.Resource: rolestr = "resource"; break;
+ default:
+ case PackageRole.Unknown: rolestr = "unknown"; break;
+ }
+ var pkgfile = new {
+ path = FilePath,
+ valid = IsValid,
+ type = typestr,
+ role = rolestr
+ };
+ #endregion
+ #region id
+ var id = Identity;
+ var pkgid = new {
+ name = id.Name,
+ publisher = id.Publisher,
+ version = id.Version.ToString (),
+ realVersion = id.RealVersion.ToString (),
+ architecture = id.ProcessArchitecture.Select (e => {
+ switch (e)
+ {
+ case Architecture.ARM: return "arm";
+ case Architecture.ARM64: return "arm64";
+ case Architecture.Neutral: return "neutral";
+ case Architecture.x64: return "x64";
+ case Architecture.x86: return "x86";
+ default:
+ case Architecture.Unknown: return "unknown";
+ }
+ }).ToList (),
+ familyName = id.FamilyName,
+ fullName = id.FullName
+ };
+ #endregion
+ #region prerequistes
+ var preq = Prerequisites;
+ var pkgpreq = new {
+ osMinVersion = preq.OSMinVersion.ToString (),
+ osMaxVersionTested = preq.OSMaxVersionTested.ToString (),
+ osMinVersionDescription = preq.OSMinVersionDescription,
+ osMaxVersionTestedDescription = preq.OSMaxVersionDescription
+ };
+ #endregion
+ #region resources
+ var res = Resources;
+ var pkgres = new {
+ languages = res.Languages,
+ scales = res.Scales,
+ dxFeatureLevels = res.DXFeatures.Select (d => {
+ switch (d)
+ {
+ case DXFeatureLevel.Level9: return 9;
+ case DXFeatureLevel.Level10: return 10;
+ case DXFeatureLevel.Level11: return 11;
+ case DXFeatureLevel.Level12: return 12;
+ default:
+ case DXFeatureLevel.Unspecified: return -1;
+ }
+ }).ToList ()
+ };
+ #endregion
+ #region capabilities
+ var caps = Capabilities;
+ var pkgcaps = new {
+ capabilities = caps.Capabilities,
+ deviceCapabilities = caps.DeviceCapabilities
+ };
+ #endregion
+ #region dependencies
+ var deps = Dependencies;
+ var pkgdeps = Dependencies.Select (d => new {
+ name = d.Name,
+ publisher = d.Publisher,
+ minVersion = d.Version.ToString ()
+ }).ToList ();
+ #endregion
+ using (var priAllRes = new PriAllValuesReader (this))
+ {
+ priAllRes.Init ();
+ #region prop
+ var prop = Properties;
+ var dispname = prop.DisplayName;
+ var dispNameDict = new Dictionary ();
+ if (PriFileHelper.IsMsResourcePrefix (dispname))
+ dispNameDict = priAllRes.LocaleResourceAllValues (dispname);
+ dispNameDict ["root"] = dispname;
+ var desc = prop.Description;
+ var descDict = new Dictionary ();
+ if (PriFileHelper.IsMsResourcePrefix (desc))
+ descDict = priAllRes.LocaleResourceAllValues (desc);
+ descDict ["root"] = desc;
+ var disppub = prop.Publisher;
+ var dispPubDict = new Dictionary ();
+ if (PriFileHelper.IsMsResourcePrefix (disppub))
+ dispPubDict = priAllRes.LocaleResourceAllValues (disppub);
+ dispPubDict ["root"] = disppub;
+ var logoList = priAllRes.FileResourceAllValues (prop.Logo)
+ .Select (kv => {
+ string contrast = "";
+ switch (kv.Key.Contrast)
+ {
+ case PriResourceKey.PriContrast.None: contrast = ""; break;
+ case PriResourceKey.PriContrast.Black: contrast = "black"; break;
+ case PriResourceKey.PriContrast.White: contrast = "white"; break;
+ case PriResourceKey.PriContrast.High: contrast = "high"; break;
+ case PriResourceKey.PriContrast.Low: contrast = "low"; break;
+ }
+
+ if (kv.Key.IsTargetSize)
+ {
+ return new {
+ targetSize = kv.Key.Value,
+ contrast = contrast,
+ name = kv.Value.Item1,
+ base64 = kv.Value.Item2
+ };
+ }
+ else if (kv.Key.IsScale)
+ {
+ return new {
+ scale = kv.Key.Value,
+ contrast = contrast,
+ name = kv.Value.Item1,
+ base64 = kv.Value.Item2
+ };
+ }
+ else if (kv.Key.IsString)
+ {
+ return new {
+ language = kv.Key.Value,
+ name = kv.Value.Item1,
+ base64 = kv.Value.Item2
+ };
+ }
+ else
+ {
+ return (dynamic)null; // 不满足条件时返回 null
+ }
+ })
+ .Where (item => item != null) // 过滤掉 null
+ .ToList ();
+ var pkgprop = new {
+ displayName = dispNameDict,
+ publisherDisplayName = dispPubDict,
+ description = descDict,
+ logo = logoList,
+ framework = prop.Framework,
+ resourcePackage = prop.ResourcePackage
+ };
+ #endregion
+ #region apps
+ var apps = Applications;
+ var pkgapps = new List