// PackageManageHelper.cs // P/Invoke wrapper for pkgmgr.dll (x86). // // 说明:此文件兼容 .NET Framework 4。 // - 将项目 Platform target 设置为 x86。 // - pkgmgr.dll 提供 PackageManagerFreeString 来释放它返回的字符串,请务必使用它释放由 pkgmgr 返回的 LPWSTR。 using System; using System.Runtime.InteropServices; namespace NativeWrappers { using DWORD = System.UInt32; using HRESULT = System.Int32; using BOOL = System.Int32; using UINT64 = System.UInt64; using System.Collections.Generic; using System.Linq; public static class PackageManageHelper { private const string DllName = "pkgmgr.dll"; private const CallingConvention CallConv = CallingConvention.Cdecl; [UnmanagedFunctionPointer (CallConv)] public delegate void PKGMRR_PROGRESSCALLBACK (DWORD dwProgress, IntPtr pCustom); [UnmanagedFunctionPointer (CallConv)] public delegate void PKGMGR_FINDENUMCALLBACK (IntPtr pNowItem, IntPtr pCustom); [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct REGISTER_PACKAGE_DEFENDENCIES { public DWORD dwSize; public IntPtr alpDepUris; // tail array } [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct FIND_PACKAGE_ID { public UINT64 qwVersion; public ushort wProcessArchitecture; [MarshalAs (UnmanagedType.ByValArray, SizeConst = 3)] public ushort [] wPadding; public IntPtr lpName; public IntPtr lpFullName; public IntPtr lpFamilyName; public IntPtr lpPublisher; public IntPtr lpPublisherId; public IntPtr lpResourceId; } [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct FIND_PACKAGE_PROPERTIES { public IntPtr lpDisplayName; public IntPtr lpDescription; public IntPtr lpPublisher; public IntPtr lpLogoUri; [MarshalAs (UnmanagedType.Bool)] public bool bIsFramework; [MarshalAs (UnmanagedType.Bool)] public bool bIsResourcePackage; [MarshalAs (UnmanagedType.Bool)] public bool bIsBundle; [MarshalAs (UnmanagedType.Bool)] public bool bIsDevelopmentMode; } [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct FIND_PACKAGE_INFO { public FIND_PACKAGE_ID piIdentity; public FIND_PACKAGE_PROPERTIES piProperties; public IntPtr lpInstallLocation; public IntPtr lpUsers; public IntPtr lpSIDs; public DWORD dwDependencesSize; public DWORD dwPadding; public UINT64 ullBuffer; } // ========== Functions ========== [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT AddAppxPackageFromPath (string lpPkgPath, IntPtr alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT AddAppxPackageFromURI (string lpFileUri, IntPtr alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT RemoveAppxPackage (string lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT CleanupAppxPackage (string lpPkgName, string lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT RegisterAppxPackageByPath (string lpManifestPath, IntPtr alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT RegisterAppxPackageByUri (string lpManifestUri, IntPtr alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT RegisterAppxPackageByFullName (string lpPackageFullName, IntPtr alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT SetAppxPackageStatus (string lpPackageFullName, DWORD dwStatus, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT StageAppxPackageFromURI (string lpFileUri, IntPtr alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT StageAppxPackageFromPath (string lpFileUri, IntPtr alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT StageAppxUserData (string lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT UpdateAppxPackageFromPath (string lpPkgPath, IntPtr alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT UpdateAppxPackageFromURI (string lpFileUri, IntPtr alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT FindAppxPackage (string lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern IntPtr GetPackageManagerLastErrorCode (); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern IntPtr GetPackageManagerLastErrorDetailMessage (); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT ActivateAppxApplication (string lpAppUserId, out DWORD pdwProcessId); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT FindAppxPackagesByIdentity (string lpPkgName, string lpPkgPublisher, PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern HRESULT FindAppxPackagesByFamilyName (string lpPkgFamilyName, PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)] public static extern void PackageManagerFreeString (IntPtr lpString); [DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern HRESULT ActivateAppxApplicationWithArgs ([MarshalAs (UnmanagedType.LPWStr)] string lpAppUserId, [MarshalAs (UnmanagedType.LPWStr)] string lpArguments, out DWORD pdwProcessId); // ========== 托管辅助 ========== public static string PtrToStringAndFree (IntPtr nativePtr) { if (nativePtr == IntPtr.Zero) return null; string s = Marshal.PtrToStringUni (nativePtr); try { PackageManagerFreeString (nativePtr); } catch { } return s; } public static FIND_PACKAGE_INFO PtrToFindPackageInfo (IntPtr pInfo) { if (pInfo == IntPtr.Zero) return default (FIND_PACKAGE_INFO); object boxed = Marshal.PtrToStructure (pInfo, typeof (FIND_PACKAGE_INFO)); return (FIND_PACKAGE_INFO)boxed; } public static string GetDisplayNameFromFindPackageInfo (IntPtr pInfo) { FIND_PACKAGE_INFO info = PtrToFindPackageInfo (pInfo); if (info.piProperties.lpDisplayName == IntPtr.Zero) return null; return Marshal.PtrToStringUni (info.piProperties.lpDisplayName); } public static string [] ReadRegisterPackageDependencies (IntPtr pReg) { if (pReg == IntPtr.Zero) return new string [0]; uint size = (uint)Marshal.ReadInt32 (pReg); if (size == 0) return new string [0]; string [] result = new string [size]; int offset = Marshal.SizeOf (typeof (uint)); for (int i = 0; i < size; i++) { IntPtr pStr = Marshal.ReadIntPtr (pReg, offset + i * IntPtr.Size); result [i] = pStr == IntPtr.Zero ? null : Marshal.PtrToStringUni (pStr); } return result; } } internal static class NativeUtil { public static string ToAbsoluteUriString (Uri uri) { if (uri == null) return null; return uri.AbsoluteUri; } public static IntPtr AllocStringArray (IEnumerable values) { if (values == null) return IntPtr.Zero; var list = values.Where (s => !string.IsNullOrEmpty (s)).ToList (); if (list.Count == 0) return IntPtr.Zero; IntPtr mem = Marshal.AllocHGlobal (IntPtr.Size * list.Count); for (int i = 0; i < list.Count; i++) { IntPtr pStr = Marshal.StringToHGlobalUni (list [i]); Marshal.WriteIntPtr (mem, i * IntPtr.Size, pStr); } return mem; } public static void FreeStringArray (IntPtr array, int count) { if (array == IntPtr.Zero) return; for (int i = 0; i < count; i++) { IntPtr p = Marshal.ReadIntPtr (array, i * IntPtr.Size); if (p != IntPtr.Zero) Marshal.FreeHGlobal (p); } Marshal.FreeHGlobal (array); } } }