using System; using System.Collections.Generic; using System.Linq; using System.Text; using AppxPackage.Info; using NativeWrappers; using System.Runtime.InteropServices; using DataUtils; using System.Net; using System.IO; namespace AppxPackage { public enum DeploymentOptions { None = 0, ForceAppShutdown = 0x00000001, DevelopmentMode = 0x00000002, InstallAllResources = 0x00000020 }; public enum PackageStatus { Normal = 0, LicenseInvalid = 1, Modified = 2, Tampered = 3 }; public static class ImageUriToBase64 { public static string ConvertToDataUri (string uriString) { if (string.IsNullOrEmpty (uriString)) throw new ArgumentNullException ("uriString"); Uri uri = new Uri (uriString, UriKind.Absolute); byte [] data; string mime; if (uri.IsFile) { string path = uri.LocalPath; data = File.ReadAllBytes (path); mime = GetMimeFromExtension (Path.GetExtension (path)); } else { using (WebClient wc = new WebClient ()) { data = wc.DownloadData (uri); mime = GetMimeFromExtension (Path.GetExtension (uri.AbsolutePath)); } } string base64 = Convert.ToBase64String (data); return "data:" + mime + ";base64," + base64; } private static string GetMimeFromExtension (string ext) { if (string.IsNullOrEmpty (ext)) return "application/octet-stream"; switch (ext.ToLowerInvariant ()) { case ".png": return "image/png"; case ".jpg": case ".jpeg": return "image/jpeg"; case ".gif": return "image/gif"; case ".bmp": return "image/bmp"; case ".webp": return "image/webp"; case ".svg": return "image/svg+xml"; default: return "application/octet-stream"; } } } [ComVisible (true)] [ClassInterface (ClassInterfaceType.AutoDual)] public class PMIdentity: IIdentity { private string name = ""; private string publisher = ""; private DataUtils.Version version = new DataUtils.Version (); private IEnumerable archs; private string familyName = ""; private string fullName = ""; private string resourceId = ""; private string publisherId = ""; public PMIdentity (string _name, string _publisher, DataUtils.Version _ver, IEnumerable _archs, string _family, string _full, string _resid, string _publisherId) { name = _name; publisher = _publisher; version = _ver; archs = _archs ?? new List (); familyName = _family; fullName = _full; resourceId = _resid; publisherId = _publisherId; } public PMIdentity (PackageManageHelper.FIND_PACKAGE_ID pkgId) : this ( Marshal.PtrToStringUni (pkgId.lpName), Marshal.PtrToStringUni (pkgId.lpPublisher), new DataUtils.Version (pkgId.qwVersion), new Architecture [] { (Architecture)pkgId.wProcessArchitecture }, Marshal.PtrToStringUni (pkgId.lpFamilyName), Marshal.PtrToStringUni (pkgId.lpFullName), Marshal.PtrToStringUni (pkgId.lpResourceId), Marshal.PtrToStringUni (pkgId.lpPublisherId) ) { } public string FamilyName => familyName; public string FullName => fullName; public string Name => name; public List ProcessArchitecture => archs.ToList (); public string Publisher => publisher; public string PublisherId => publisherId; public string ResourceId => resourceId; public DataUtils.Version Version => version; } [ComVisible (true)] [ClassInterface (ClassInterfaceType.AutoDual)] public class PMProperties: IProperties { private string desc = ""; private string displayName = ""; private bool framework = false; private string logo = ""; private string publisher = ""; private bool isres = false; public PMProperties (string _name, string _pub, string _desc, string _logo, bool _fw, bool _res) { desc = _desc; displayName = _name; framework = _fw; logo = _logo; publisher = _pub; isres = _res; } public PMProperties (PackageManageHelper.FIND_PACKAGE_PROPERTIES prop) : this ( Marshal.PtrToStringUni (prop.lpDisplayName), Marshal.PtrToStringUni (prop.lpPublisher), Marshal.PtrToStringUni (prop.lpDescription), Marshal.PtrToStringUni (prop.lpLogoUri), prop.bIsFramework, prop.bIsResourcePackage ) { } public string Description => desc; public string DisplayName => displayName; public bool Framework => framework; public string Logo => logo; public string LogoBase64 { get { try { return ImageUriToBase64.ConvertToDataUri (Logo); } catch (Exception) { } return ""; } } public string Publisher => publisher; public bool ResourcePackage => isres; } [ComVisible (true)] [ClassInterface (ClassInterfaceType.AutoDual)] public class PMPackageInfo { public PMIdentity Identity { get; private set; } public PMProperties Properties { get; private set; } public bool IsBundle { get; private set; } public bool DevelopmentMode { get; private set; } public string InstallLocation { get; private set; } public List Users { get; private set; } public List SIDs { get; private set; } public PMPackageInfo (PackageManageHelper.FIND_PACKAGE_INFO info) { Identity = new PMIdentity (info.piIdentity); Properties = new PMProperties (info.piProperties); IsBundle = info.piProperties.bIsBundle; DevelopmentMode = info.piProperties.bIsDevelopmentMode; InstallLocation = Marshal.PtrToStringUni (info.lpInstallLocation); Users = (Marshal.PtrToStringUni (info.lpUsers) ?? "").Split (';').ToList (); SIDs = (Marshal.PtrToStringUni (info.lpSIDs) ?? "").Split (';').ToList (); } } [ComVisible (true)] [ClassInterface (ClassInterfaceType.AutoDual)] public static class PackageManager { private static DataUtils._I_HResult FromNative (int hr,IntPtr pErrorCode,IntPtr pDetailMsg) { string errCode = null; string detail = null; try { if (pErrorCode != IntPtr.Zero) errCode = Marshal.PtrToStringUni (pErrorCode); if (pDetailMsg != IntPtr.Zero) detail = Marshal.PtrToStringUni (pDetailMsg); } finally { if (pErrorCode != IntPtr.Zero) PackageManageHelper.PackageManagerFreeString (pErrorCode); if (pDetailMsg != IntPtr.Zero) PackageManageHelper.PackageManagerFreeString (pDetailMsg); } return new DataUtils._I_HResult (hr, errCode, detail); } public delegate void PackageProgressCallback (uint progress); internal sealed class ProgressCallbackHolder { private readonly PackageProgressCallback _callback; public ProgressCallbackHolder (PackageProgressCallback cb) { _callback = cb; Native = new PackageManageHelper.PKGMRR_PROGRESSCALLBACK (OnNative); } public PackageManageHelper.PKGMRR_PROGRESSCALLBACK Native { get; private set; } private void OnNative (uint progress, IntPtr custom) { if (_callback != null) _callback (progress); } } internal sealed class ResultCallbackHolder { public readonly List RetList = new List (); public PackageManageHelper.PKGMGR_FINDENUMCALLBACK Callback; public ResultCallbackHolder () { Callback = OnResult; } private void OnResult ( IntPtr nativeInfo, IntPtr pCustom) { RetList.Add (new PMPackageInfo (PackageManageHelper.PtrToFindPackageInfo (nativeInfo))); } } public static DataUtils._I_HResult AddPackage (Uri fileUri, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { if (fileUri == null) throw new ArgumentNullException ("Required File URI"); IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.Select (u => u.AbsoluteUri).ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.AddAppxPackageFromURI (fileUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult AddPackage (string filePath, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.AddAppxPackageFromPath (filePath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static Tuple > GetPackages () { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ResultCallbackHolder callback = null; try { callback = new ResultCallbackHolder (); int hr = PackageManageHelper.GetAppxPackages (callback.Callback, IntPtr.Zero, out pErrCode, out pDetail); return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList); } finally { GC.KeepAlive (callback); } } public static DataUtils._I_HResult RemovePackage (string packageFullName, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ProgressCallbackHolder holder = null; try { PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.RemoveAppxPackage (packageFullName, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { GC.KeepAlive (holder); } } public static DataUtils._I_HResult ClearupPackage (string packageName, string userSID, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ProgressCallbackHolder holder = null; try { PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.CleanupAppxPackage (packageName, userSID, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { GC.KeepAlive (holder); } } public static DataUtils._I_HResult RegisterPackage (Uri manifestUri, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { if (manifestUri == null) throw new ArgumentNullException ("Required File URI"); IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.Select (u => u.AbsoluteUri).ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.RegisterAppxPackageByUri (manifestUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult RegisterPackage (string manifestPath, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.RegisterAppxPackageByUri (manifestPath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult RegisterPackageByFullName (string pkgFullName, IEnumerable depFullNames, DeploymentOptions options, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depFullNames == null ? new List () : depFullNames.ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.RegisterAppxPackageByFullName (pkgFullName, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult SetPackageStatus (string packageFullName, PackageStatus status) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; try { int hr = PackageManageHelper.SetAppxPackageStatus (packageFullName, (uint)status, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { } } public static DataUtils._I_HResult StagePackage (Uri fileUri, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { if (fileUri == null) throw new ArgumentNullException ("Required File URI"); IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.Select (u => u.AbsoluteUri).ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.StageAppxPackageFromURI (fileUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult StagePackage (string filePath, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.StageAppxPackageFromPath (filePath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult StageUserData (string packageFullName, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ProgressCallbackHolder holder = null; try { PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.StageAppxUserData (packageFullName, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { GC.KeepAlive (holder); } } public static DataUtils._I_HResult UpdatePackage (Uri fileUri, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { if (fileUri == null) throw new ArgumentNullException ("Required File URI"); IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.Select (u => u.AbsoluteUri).ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.UpdateAppxPackageFromURI (fileUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static DataUtils._I_HResult UpdatePackage (string filePath, IEnumerable depUris, DeploymentOptions options, PackageProgressCallback progress = null) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; var depList = depUris == null ? new List () : depUris.ToList (); ProgressCallbackHolder holder = null; try { depArray = NativeUtil.AllocStringArray (depList); PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null; if (progress != null) { holder = new ProgressCallbackHolder (progress); nativeCb = holder.Native; } int hr = PackageManageHelper.UpdateAppxPackageFromPath (filePath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail); return FromNative (hr, pErrCode, pDetail); } finally { NativeUtil.FreeStringArray (depArray, depList.Count); GC.KeepAlive (holder); } } public static Tuple> FindPackage (string packageName, string packagePublisher) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ResultCallbackHolder callback = null; try { callback = new ResultCallbackHolder (); int hr = PackageManageHelper.FindAppxPackagesByIdentity (packageName, packagePublisher, callback.Callback, IntPtr.Zero, out pErrCode, out pDetail); return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList); } finally { GC.KeepAlive (callback); } } public static Tuple> FindPackage (string packageFamilyName) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ResultCallbackHolder callback = null; try { callback = new ResultCallbackHolder (); int hr = PackageManageHelper.FindAppxPackagesByFamilyName (packageFamilyName, callback.Callback, IntPtr.Zero, out pErrCode, out pDetail); return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList); } finally { GC.KeepAlive (callback); } } public static Tuple> FindPackageByFullName (string packageFullName) { IntPtr depArray = IntPtr.Zero; IntPtr pErrCode = IntPtr.Zero; IntPtr pDetail = IntPtr.Zero; ResultCallbackHolder callback = null; try { callback = new ResultCallbackHolder (); int hr = PackageManageHelper.FindAppxPackage (packageFullName, callback.Callback, IntPtr.Zero, out pErrCode, out pDetail); return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList); } finally { GC.KeepAlive (callback); } } public static DataUtils._I_HResult ActiveApp (string appUserId) { uint processId; var hr = PackageManageHelper.ActivateAppxApplication (appUserId, out processId); return new DataUtils._I_HResult (hr); } public static DataUtils._I_HResult ActiveApp (string appUserId, string cmdargs) { uint processId; var hr = PackageManageHelper.ActivateAppxApplicationWithArgs (appUserId, cmdargs, out processId); return new DataUtils._I_HResult (hr); } } }