Coding for Package Manager.

This commit is contained in:
Bruce
2026-01-20 22:34:22 +08:00
parent 7483ed6930
commit 75cb72964d
71 changed files with 5518 additions and 13351 deletions
+16
View File
@@ -48,6 +48,10 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@@ -57,12 +61,24 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DataInterface.cs" />
<Compile Include="PackageManager.cs" />
<Compile Include="PackageReader.cs" />
<Compile Include="PkgMgrNative.cs" />
<Compile Include="PkgReadNative.cs" />
<Compile Include="PriFileNative.cs" />
<Compile Include="PriReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DataUtils\DataUtils.csproj">
<Project>{ffd3fd52-37a8-4f43-883c-de8d996cb0e0}</Project>
<Name>DataUtils</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+232
View File
@@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace AppxPackage
{
[Serializable]
public sealed class Ref<T>
{
private T _value;
public Ref ()
{
_value = default (T);
}
public Ref (T value)
{
_value = value;
}
/// <summary>
/// 模拟 & 引用访问
/// </summary>
public T Value
{
get { return _value; }
set { _value = value; }
}
/// <summary>
/// 直接赋值(像 *ref = value
/// </summary>
public void Set (T value)
{
_value = value;
}
/// <summary>
/// 取值(像 value = *ref
/// </summary>
public T Get ()
{
return _value;
}
public override string ToString ()
{
return _value == null ? string.Empty : _value.ToString ();
}
public override int GetHashCode ()
{
return _value == null ? 0 : _value.GetHashCode ();
}
public override bool Equals (object obj)
{
if (ReferenceEquals (this, obj)) return true;
if (obj is Ref<T>) return Equals (_value, ((Ref<T>)obj)._value);
return Equals (_value, obj);
}
public static implicit operator T (Ref<T> r)
{
return r == null ? default (T) : r._value;
}
public static implicit operator Ref<T>(T value)
{
return new Ref<T> (value);
}
}
}
namespace AppxPackage.Info
{
public enum Architecture
{
x86 = 0,
ARM = 5,
x64 = 9,
Neutral = 11,
ARM64 = 12,
Unknown = ushort.MaxValue
};
public enum PackageType
{
Unknown = 0,
Appx = 1,
Bundle = 2
};
public enum PackageRole
{
Unknown = 0,
Application = 1,
Framework = 2,
Resource = 3
};
public interface IIdentity
{
string Name { get; }
string Publisher { get; }
string FamilyName { get; }
string FullName { get; }
string ResourceId { get; }
DataUtils.Version Version { get; }
List<Architecture> ProcessArchitecture { get; }
}
public interface IProperties
{
string DisplayName { get; }
string Description { get; }
string Publisher { get; }
string Logo { get; }
string LogoBase64 { get; }
bool Framework { get; }
bool ResourcePackage { get; }
}
public interface ICapabilities
{
List<string> Capabilities { get; }
List<string> DeviceCapabilities { get; }
}
public class DependencyInfo
{
public string Name { get; private set; } = "";
public string Publisher { get; private set; } = "";
public DataUtils.Version Version { get; private set; } = new DataUtils.Version ();
public DependencyInfo (string name, string publisher, DataUtils.Version ver)
{
Name = name;
Publisher = publisher;
Version = ver;
}
public DependencyInfo (string name, DataUtils.Version ver): this (name, "", ver) { }
public DependencyInfo () { }
}
public enum DXFeatureLevel
{
Unspecified = 0,
Level9 = 0x1,
Level10 = 0x2,
Level11 = 0x4,
Level12 = 0x8
}
public interface IResources
{
List <string> Languages { get; }
List <int> Languages_LCID { get; }
List <int> Scales { get; }
List <DXFeatureLevel> DXFeatures { get; }
}
public interface IPrerequisites
{
DataUtils.Version OSMinVersion { get; }
DataUtils.Version OSMaxVersionTested { get; }
string OSMinVersionDescription { get; }
string OSMaxVersionDescription { get; }
}
[Serializable]
[StructLayout (LayoutKind.Sequential)]
public struct HRESULT: IEquatable<HRESULT>
{
private readonly int _value;
public HRESULT (int value)
{
_value = value;
}
public int Value
{
get { return _value; }
}
public bool Succeeded
{
get { return _value >= 0; }
}
public bool Failed
{
get { return _value < 0; }
}
public void ThrowIfFailed ()
{
if (Failed)
Marshal.ThrowExceptionForHR (_value);
}
public Exception GetException ()
{
return Failed ? Marshal.GetExceptionForHR (_value) : null;
}
public override string ToString ()
{
return string.Format ("HRESULT 0x{0:X8}", _value);
}
public override int GetHashCode ()
{
return _value;
}
public override bool Equals (object obj)
{
if (obj is HRESULT) return Equals ((HRESULT)obj);
return false;
}
public bool Equals (HRESULT other)
{
return _value == other._value;
}
public static implicit operator int (HRESULT hr)
{
return hr._value;
}
public static implicit operator HRESULT (int value)
{
return new HRESULT (value);
}
public static bool operator == (HRESULT a, HRESULT b)
{
return a._value == b._value;
}
public static bool operator != (HRESULT a, HRESULT b)
{
return a._value != b._value;
}
public static bool operator >= (HRESULT a, int value)
{
return a._value >= value;
}
public static bool operator <= (HRESULT a, int value)
{
return a._value <= value;
}
public static bool operator > (HRESULT a, int value)
{
return a._value > value;
}
public static bool operator < (HRESULT a, int value)
{
return a._value < value;
}
}
}
+603
View File
@@ -0,0 +1,603 @@
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<Architecture> archs;
private string familyName = "";
private string fullName = "";
private string resourceId = "";
public PMIdentity (string _name, string _publisher, DataUtils.Version _ver, IEnumerable<Architecture> _archs, string _family, string _full, string _resid)
{
name = _name;
publisher = _publisher;
version = _ver;
archs = _archs ?? new List<Architecture> ();
familyName = _family;
fullName = _full;
resourceId = _resid;
}
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)
)
{ }
public string FamilyName => familyName;
public string FullName => fullName;
public string Name => name;
public List<Architecture> ProcessArchitecture => archs.ToList ();
public string Publisher => publisher;
public string ResourceId => resourceId;
DataUtils.Version IIdentity.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<string> Users { get; private set; }
public List<string> 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<PMPackageInfo> RetList = new List<PMPackageInfo> ();
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<Uri> 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<string> () : 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<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
{
IntPtr depArray = IntPtr.Zero;
IntPtr pErrCode = IntPtr.Zero;
IntPtr pDetail = IntPtr.Zero;
var depList = depUris == null ? new List<string> () : 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 <DataUtils._I_HResult, List <PMPackageInfo>> 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<Uri> 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<string> () : 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<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
{
IntPtr depArray = IntPtr.Zero;
IntPtr pErrCode = IntPtr.Zero;
IntPtr pDetail = IntPtr.Zero;
var depList = depUris == null ? new List<string> () : 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<string> depFullNames, DeploymentOptions options, PackageProgressCallback progress = null)
{
IntPtr depArray = IntPtr.Zero;
IntPtr pErrCode = IntPtr.Zero;
IntPtr pDetail = IntPtr.Zero;
var depList = depFullNames == null ? new List<string> () : 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<Uri> 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<string> () : 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<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
{
IntPtr depArray = IntPtr.Zero;
IntPtr pErrCode = IntPtr.Zero;
IntPtr pDetail = IntPtr.Zero;
var depList = depUris == null ? new List<string> () : 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<Uri> 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<string> () : 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<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
{
IntPtr depArray = IntPtr.Zero;
IntPtr pErrCode = IntPtr.Zero;
IntPtr pDetail = IntPtr.Zero;
var depList = depUris == null ? new List<string> () : 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<DataUtils._I_HResult, List<PMPackageInfo>> 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<DataUtils._I_HResult, List<PMPackageInfo>> 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<DataUtils._I_HResult, List<PMPackageInfo>> 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);
}
}
}
}
File diff suppressed because it is too large Load Diff
+39
View File
@@ -14,6 +14,8 @@ namespace NativeWrappers
using HRESULT = System.Int32;
using BOOL = System.Int32;
using UINT64 = System.UInt64;
using System.Collections.Generic;
using System.Linq;
public static class PackageManageHelper
{
@@ -186,4 +188,41 @@ namespace NativeWrappers
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<string> 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);
}
}
}
+6
View File
@@ -218,6 +218,12 @@ namespace NativeWrappers
}
return s;
}
public static string GetStringFromPkgRead (IntPtr nativePtr)
{
if (nativePtr == IntPtr.Zero) return null;
string s = Marshal.PtrToStringUni (nativePtr);
return s;
}
public static string PtrToStringNoFree (IntPtr nativePtr)
{
+38 -10
View File
@@ -32,10 +32,10 @@ namespace AppxPackage
public static extern string PriFileGetLastError ();
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void FindPriStringResource (PCSPRIFILE pFilePri, ref LPCWSTRLIST hUriList);
public static extern void FindPriStringResource (PCSPRIFILE pFilePri, IntPtr hUriList);
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void FindPriPathResource (PCSPRIFILE pFilePri, ref LPCWSTRLIST hPathList);
public static extern void FindPriPathResource (PCSPRIFILE pFilePri, IntPtr hPathList);
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void ClearPriCacheData ();
@@ -44,7 +44,7 @@ namespace AppxPackage
public static extern IntPtr GetPriResource (PCSPRIFILE pFilePri, [MarshalAs (UnmanagedType.LPWStr)] string lpswResId);
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void FindPriResource (PCSPRIFILE pFilePri, ref LPCWSTRLIST hUriList);
public static extern void FindPriResource (PCSPRIFILE pFilePri, IntPtr hUriList);
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.Bool)]
@@ -64,14 +64,42 @@ namespace AppxPackage
Marshal.FreeHGlobal (ptr); // 如果 DLL 返回的内存要求 free
return s;
}
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void FreePriString (IntPtr p);
}
[StructLayout (LayoutKind.Sequential)]
public struct LPCWSTRLIST
public static class LpcwstrListHelper
{
public uint dwLength; // DWORD
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 1)]
public IntPtr [] aswArray; // LPCWSTR*,数组
}
public static IntPtr Create (IEnumerable<string> strings)
{
if (strings == null) return IntPtr.Zero;
var list = new List<string> (strings);
int count = list.Count;
int size = sizeof (uint) + IntPtr.Size * count;
IntPtr pMem = Marshal.AllocHGlobal (size);
Marshal.WriteInt32 (pMem, count);
IntPtr pArray = pMem + sizeof (uint);
for (int i = 0; i < count; i++)
{
IntPtr pStr = Marshal.StringToHGlobalUni (list [i]);
Marshal.WriteIntPtr (pArray, i * IntPtr.Size, pStr);
}
return pMem;
}
public static void Destroy (IntPtr pList)
{
if (pList == IntPtr.Zero)
return;
int count = Marshal.ReadInt32 (pList);
IntPtr pArray = pList + sizeof (uint);
for (int i = 0; i < count; i++)
{
IntPtr pStr = Marshal.ReadIntPtr (pArray, i * IntPtr.Size);
if (pStr != IntPtr.Zero)
Marshal.FreeHGlobal (pStr);
}
Marshal.FreeHGlobal (pList);
}
}
}
+241 -2
View File
@@ -2,11 +2,250 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
namespace AppxPackage
{
class PriReader
public class PriReader: IDisposable
{
private IntPtr m_hPriFile = IntPtr.Zero;
public bool Valid { get { return m_hPriFile != IntPtr.Zero; } }
public void Dispose ()
{
if (Valid)
{
PriFileHelper.DestroyPriFileInstance (m_hPriFile);
m_hPriFile = IntPtr.Zero;
}
}
~PriReader () { Dispose (); }
public bool Create (IStream isfile)
{
try
{
Dispose ();
if (isfile == null) return false;
var pStream = Marshal.GetComInterfaceForObject (isfile, typeof (IStream));
m_hPriFile = PriFileHelper.CreatePriFileInstanceFromStream (pStream);
}
catch (Exception) { m_hPriFile = IntPtr.Zero; }
return Valid;
}
public bool Create (IntPtr pStream)
{
try
{
Dispose ();
if (pStream == IntPtr.Zero) return false;
m_hPriFile = PriFileHelper.CreatePriFileInstanceFromStream (pStream);
}
catch (Exception) { m_hPriFile = IntPtr.Zero; }
return Valid;
}
public bool Create ([MarshalAs (UnmanagedType.LPWStr)] string filePath)
{
try
{
Dispose ();
if (string.IsNullOrWhiteSpace (filePath)) return false;
m_hPriFile = PriFileHelper.CreatePriFileInstanceFromPath (filePath);
}
catch (Exception) { m_hPriFile = IntPtr.Zero; }
return Valid;
}
public PriReader (IStream isfile) { Create (isfile); }
public PriReader (IntPtr pStream) { Create (pStream); }
public PriReader ([MarshalAs (UnmanagedType.LPWStr)] string fileName) { Create (fileName); }
public PriReader () { }
public void AddSearch (IEnumerable <string> arr)
{
IntPtr buf = IntPtr.Zero;
try
{
if (arr == null) return;
buf = LpcwstrListHelper.Create (arr);
PriFileHelper.FindPriResource (m_hPriFile, buf);
}
finally
{
if (buf != IntPtr.Zero) LpcwstrListHelper.Destroy (buf);
}
}
public void AddSearch (string uri) { AddSearch (new string [] { uri }); }
public string Resource (string resName)
{
IntPtr ret = IntPtr.Zero;
try
{
ret = PriFileHelper.GetPriResource (m_hPriFile, resName);
if (ret == IntPtr.Zero) return string.Empty;
return PriFileHelper.PtrToString (ret);
}
finally
{
if (ret != IntPtr.Zero) PriFileHelper.FreePriString (ret);
}
}
public Dictionary<string, string> Resources (IEnumerable<string> resnames)
{
if (resnames == null) throw new ArgumentNullException (nameof (resnames));
var result = new Dictionary<string, string> ();
AddSearch (resnames);
foreach (var name in resnames) result [name] = Resource (name);
return result;
}
public static string LastError { get { return PriFileHelper.PriFileGetLastError (); } }
public string Path (string resName) { return Resource (resName); }
public Dictionary <string, string> Paths (IEnumerable <string> resNames) { return Resources (resNames); }
public string String (string resName) { return Resource (resName); }
public Dictionary <string, string> Strings (IEnumerable <string> resNames) { return Resources (resNames); }
}
public class PriReaderBundle: IDisposable
{
private class PriInst
{
public byte Type; // 0b01 lang, 0b10 scale, 0b11 both
public PriReader Reader;
public PriInst (byte type, IStream stream)
{
Type = (byte)(type & 0x03);
Reader = new PriReader (stream);
}
public PriInst (byte type, IntPtr stream)
{
Type = (byte)(type & 0x03);
Reader = new PriReader (stream);
}
public bool IsValid
{
get { return (Type & 0x03) != 0; }
}
}
private readonly List<PriInst> _priFiles = new List<PriInst> (3);
private readonly Dictionary<byte, PriInst> _mapPri = new Dictionary<byte, PriInst> ();
// type: 1 language, 2 scale, 3 both
public bool Set (byte type, IStream priStream)
{
byte realType = (byte)(type & 0x03);
if (realType == 0) return false;
PriInst inst;
if (_mapPri.TryGetValue (realType, out inst))
{
inst.Reader.Dispose ();
if (priStream != null) inst.Reader.Create (priStream);
}
else
{
if (priStream == null) return false;
inst = new PriInst (realType, priStream);
_priFiles.Add (inst);
_mapPri [realType] = inst;
}
return true;
}
public bool Set (byte type, IntPtr priStream)
{
byte realType = (byte)(type & 0x03);
if (realType == 0) return false;
PriInst inst;
if (_mapPri.TryGetValue (realType, out inst))
{
inst.Reader.Dispose ();
if (priStream != IntPtr.Zero) inst.Reader.Create (priStream);
}
else
{
if (priStream == IntPtr.Zero) return false;
inst = new PriInst (realType, priStream);
_priFiles.Add (inst);
_mapPri [realType] = inst;
}
return true;
}
private PriReader Get (byte type, bool mustReturn)
{
type = (byte)(type & 0x03);
PriInst inst;
if (_mapPri.TryGetValue (type, out inst)) return inst.Reader;
if (type != 0x03 && _mapPri.TryGetValue (0x03, out inst)) return inst.Reader;
if (_priFiles.Count > 0 && mustReturn) return _priFiles [0].Reader;
return null;
}
private static bool IsMsResourcePrefix (string s)
{
return PriFileHelper.IsMsResourcePrefix (s);
}
public void AddSearch (IEnumerable<string> arr)
{
if (arr == null) return;
List<string> strRes = new List<string> ();
List<string> pathRes = new List<string> ();
foreach (string it in arr)
{
if (IsMsResourcePrefix (it)) strRes.Add (it);
else pathRes.Add (it);
}
PriReader langPri = Get (1, true);
PriReader scalePri = Get (2, true);
if (langPri != null && strRes.Count > 0) langPri.AddSearch (strRes);
if (scalePri != null && pathRes.Count > 0) scalePri.AddSearch (pathRes);
}
public void AddSearch (string resName)
{
if (IsMsResourcePrefix (resName))
{
PriReader langPri = Get (1, true);
if (langPri != null) langPri.AddSearch (resName);
}
else
{
PriReader scalePri = Get (2, true);
if (scalePri != null) scalePri.AddSearch (resName);
}
}
public string Resource (string resName)
{
if (IsMsResourcePrefix (resName))
{
PriReader langPri = Get (1, true);
return langPri != null ? langPri.Resource (resName) : string.Empty;
}
else
{
PriReader scalePri = Get (2, true);
return scalePri != null ? scalePri.Resource (resName) : string.Empty;
}
}
public Dictionary<string, string> Resources (IEnumerable<string> resNames)
{
if (resNames == null) throw new ArgumentNullException ("resNames");
Dictionary<string, string> result = new Dictionary<string, string> ();
AddSearch (resNames);
foreach (string name in resNames) result [name] = Resource (name);
return result;
}
public string Path (string resName)
{
return Resource (resName);
}
public Dictionary<string, string> Paths (IEnumerable<string> resNames)
{
return Resources (resNames);
}
public string String (string resName)
{
return Resource (resName);
}
public Dictionary<string, string> Strings (IEnumerable<string> resNames)
{
return Resources (resNames);
}
public void Dispose ()
{
foreach (PriInst it in _priFiles) it.Reader.Dispose ();
_mapPri.Clear ();
_priFiles.Clear ();
}
}
}
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
</packages>