Skip to content

Commit fb07f81

Browse files
committed
Collapse mostly empty PackageManagement class into ManifestInformation.
1 parent 7489f96 commit fb07f81

2 files changed

Lines changed: 137 additions & 148 deletions

File tree

src/PSADT/PSADT/AppManagement/ManifestInformation.cs

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
using System;
2+
using System.IO;
3+
using System.IO.Compression;
4+
using System.Runtime.InteropServices;
5+
using PSADT.Interop;
26
using Windows.Win32.Storage.Packaging.Appx;
7+
using Windows.Win32.System.Com;
38

49
namespace PSADT.AppManagement
510
{
@@ -8,12 +13,28 @@ namespace PSADT.AppManagement
813
/// </summary>
914
public sealed record ManifestInformation
1015
{
16+
/// <summary>
17+
/// Retrieves the manifest information from the specified package file by determining the package type and reading the appropriate manifest file within the package archive.
18+
/// </summary>
19+
/// <param name="packageUri">The URI to the package file.</param>
20+
/// <returns>The manifest information.</returns>
21+
/// <exception cref="InvalidOperationException">Thrown if the package file is not a valid Appx/Msix package or bundle.</exception>
22+
public static ManifestInformation Get(Uri packageUri)
23+
{
24+
return DeterminePackageType(packageUri) switch
25+
{
26+
PackageType.Package => GetPackageManifestInformation(packageUri),
27+
PackageType.Bundle => GetBundleManifestInformation(packageUri),
28+
_ => throw new InvalidOperationException("The specified package file is not a valid Appx/Msix package or bundle."),
29+
};
30+
}
31+
1132
/// <summary>
1233
/// Initializes a new instance of the <see cref="ManifestInformation"/> record based on the provided <see cref="IAppxManifestPackageId"/>.
1334
/// </summary>
1435
/// <param name="packageId">The package ID from which to initialize the package information.</param>
1536
/// <param name="packageType">The type of the package (single package or bundle).</param>
16-
internal ManifestInformation(IAppxManifestPackageId packageId, AppxPackageType packageType)
37+
private ManifestInformation(IAppxManifestPackageId packageId, PackageType packageType)
1738
{
1839
Name = packageId.GetName().ToString();
1940
Architecture = (Interop.APPX_PACKAGE_ARCHITECTURE)packageId.GetArchitecture();
@@ -64,6 +85,120 @@ internal ManifestInformation(IAppxManifestPackageId packageId, AppxPackageType p
6485
/// <summary>
6586
/// Gets the type of the package (single package or bundle) based on the presence of specific manifest files within the package archive.
6687
/// </summary>
67-
public AppxPackageType PackageType { get; }
88+
public PackageType PackageType { get; }
89+
90+
/// <summary>
91+
/// Determines the type of the package (single package or bundle) by checking for the presence of specific manifest files within the package archive.
92+
/// </summary>
93+
/// <param name="packageUri">The URI to the package file.</param>
94+
/// <returns>The type of the package.</returns>
95+
/// <exception cref="InvalidOperationException">Thrown if the package file is not a valid Appx/Msix package or bundle.</exception>
96+
private static PackageType DeterminePackageType(Uri packageUri)
97+
{
98+
// Check for the presence of a bundle manifest file to determine if it's a bundle.
99+
using ZipArchive archive = ZipFile.OpenRead(packageUri.LocalPath);
100+
return archive.GetEntry("AppxMetadata/AppxBundleManifest.xml") is not null ? PackageType.Bundle : archive.GetEntry("AppxManifest.xml") is not null ? PackageType.Package
101+
: throw new InvalidOperationException("The specified package file is not a valid Appx/Msix package or bundle.");
102+
}
103+
104+
/// <summary>
105+
/// Reads the package information from the specified package file by opening it as an IStream and using the AppxFactory COM interfaces.
106+
/// </summary>
107+
/// <param name="packageUri">The URI to the package file.</param>
108+
/// <returns>The package information.</returns>
109+
private static ManifestInformation GetPackageManifestInformation(Uri packageUri)
110+
{
111+
_ = NativeMethods.SHCreateStreamOnFileEx(packageUri.LocalPath, Interop.STGM.STGM_READ | Interop.STGM.STGM_SHARE_DENY_NONE, FileAttributes.Normal, fCreate: false, pstmTemplate: null, out IStream packageStream);
112+
try
113+
{
114+
IAppxFactory appxFactory = (IAppxFactory)new AppxFactory();
115+
try
116+
{
117+
IAppxPackageReader packageReader = appxFactory.CreatePackageReader(packageStream);
118+
try
119+
{
120+
IAppxManifestReader manifestReader = packageReader.GetManifest();
121+
try
122+
{
123+
IAppxManifestPackageId packageId = manifestReader.GetPackageId();
124+
try
125+
{
126+
return new(packageId, PackageType.Package);
127+
}
128+
finally
129+
{
130+
_ = Marshal.FinalReleaseComObject(packageId);
131+
}
132+
}
133+
finally
134+
{
135+
_ = Marshal.FinalReleaseComObject(manifestReader);
136+
}
137+
}
138+
finally
139+
{
140+
_ = Marshal.FinalReleaseComObject(packageReader);
141+
}
142+
}
143+
finally
144+
{
145+
_ = Marshal.FinalReleaseComObject(appxFactory);
146+
}
147+
}
148+
finally
149+
{
150+
_ = Marshal.FinalReleaseComObject(packageStream);
151+
}
152+
}
153+
154+
/// <summary>
155+
/// Reads the package information from the specified bundle file by opening it as an IStream and using the AppxBundleFactory COM interfaces.
156+
/// </summary>
157+
/// <param name="packageUri">The URI to the bundle file.</param>
158+
/// <returns>The package information.</returns>
159+
private static ManifestInformation GetBundleManifestInformation(Uri packageUri)
160+
{
161+
_ = NativeMethods.SHCreateStreamOnFileEx(packageUri.LocalPath, Interop.STGM.STGM_READ | Interop.STGM.STGM_SHARE_DENY_NONE, FileAttributes.Normal, fCreate: false, pstmTemplate: null, out IStream packageStream);
162+
try
163+
{
164+
IAppxBundleFactory appxFactory = (IAppxBundleFactory)new AppxBundleFactory();
165+
try
166+
{
167+
IAppxBundleReader packageReader = appxFactory.CreateBundleReader(packageStream);
168+
try
169+
{
170+
IAppxBundleManifestReader manifestReader = packageReader.GetManifest();
171+
try
172+
{
173+
IAppxManifestPackageId packageId = manifestReader.GetPackageId();
174+
try
175+
{
176+
return new(packageId, PackageType.Bundle);
177+
}
178+
finally
179+
{
180+
_ = Marshal.FinalReleaseComObject(packageId);
181+
}
182+
}
183+
finally
184+
{
185+
_ = Marshal.FinalReleaseComObject(manifestReader);
186+
}
187+
}
188+
finally
189+
{
190+
_ = Marshal.FinalReleaseComObject(packageReader);
191+
}
192+
}
193+
finally
194+
{
195+
_ = Marshal.FinalReleaseComObject(appxFactory);
196+
}
197+
}
198+
finally
199+
{
200+
_ = Marshal.FinalReleaseComObject(packageStream);
201+
}
202+
}
68203
}
69204
}

src/PSADT/PSADT/AppManagement/PackageManagement.cs

Lines changed: 0 additions & 146 deletions
This file was deleted.

0 commit comments

Comments
 (0)