Skip to the content.

Experimental AppInstall foundation

Unpublished module boundary

The five implemented commands belong to the repository-local Shmuelie.AppInstall.Experimental module, not Shmuelie.Windows. The supported Windows module still owns Get-AppInstallerApp and Update-AppInstallerApp, which use a different API family. Normal Windows builds, default tests and release packages exclude AppInstallManager.

The experimental implementation, help, formatting and fake tests are preserved under experimental/Shmuelie.AppInstall.Experimental/. Its explicit build target is Build-Module.ps1 -Module Shmuelie.AppInstall.Experimental; fake validation uses Invoke-Tests.ps1 -Path experimental/Shmuelie.AppInstall.Experimental/tests. Run either only after validation is authorized. The manual experimental workflow does not publish, and both repository publication entry points reject this module. There is no Gallery installation path or release authorization.

Consumers of unpublished source builds must update the module/manifest name. The Shmuelie.Windows.AppInstall assembly, CLR namespaces and serialized type names remain unchanged to preserve experimental contracts and evidence.

Microsoft documents AppInstallManager access as protected by a private capability restricted to Microsoft-developed apps. Observed activation and selected calls are empirical evidence, not an official third-party support guarantee. runFullTrust, administrator access and successful context creation must not be interpreted as authorization. No capability bypass is provided.

The scope decision in #232 permits this foundation while #233 remains open for support clarification. Other API families retain their approval prerequisites. The separately approved caller-context reads in #236 and #238 are implemented; #233 no longer blocks this read-only subset, but does not authorize setters or broader operations. The approved caller-scoped all-app paused search in #244 is also implemented with explicit confirmation. Other #244 variants remain gated.

Context contract

New-AppInstallContext is an in-process compiled PowerShell 7.4+ command, available on Windows 10 build 19041 or later. It creates an Shmuelie.Windows.AppInstall.AppInstallContext without native activation. Use -WhatIf to avoid even this local allocation. It exposes:

Property Meaning
ContextId Local context correlation ID, not a native installation or account ID
RunspaceId Creating PowerShell runspace
UserScope Caller; does not imply a SID, known account or all-user visibility
IsActivated Whether lazy native activation succeeded, not authorization for other operations
IsDisposed Whether the context has ended its lifetime

Call Dispose() in finally. Disposal is idempotent and also occurs when the creating runspace closes or breaks. Module removal does not end caller-owned contexts. Neither disposal nor stopping a future local wait implicitly cancels remote queued work. No native manager is exposed publicly.

Each context owns one lazy manager. The internal Use integration seam checks runspace ownership, platform and exact member availability before activation or invocation. Native activation errors are retained, including their HRESULT; a failed activation is cached rather than retried invisibly. A new explicit context is required to retry activation. Metadata presence is not an access check.

Use callbacks must perform only a short native invocation. Wait for any returned async operation outside the context lifecycle lock. Disposal/local cancellation is not a hard timeout or a way to forcibly cancel a synchronous WinRT call. Independently owned managers do not isolate native device-wide settings: for example, AutoUpdateSetting is documented as a device setting. No settings writes are implemented.

Later cmdlets must accept this explicit context rather than create an undocumented manager per invocation or share mutable global settings. The internal manager adapter provides caller-scoped queue and settings reads through Get-AppInstallItem and Get-AppInstallSettings, and only the approved paused search through Request-AppInstallUpdateSearch. No settings writes, queue controls or ForUser operation is included.

Read-only settings

Get-AppInstallSettings -Context $context [-Property <exact names>] requires the explicit, live, current-runspace context from New-AppInstallContext. It never allocates a hidden manager. The default selection is AutoUpdateSetting and CanInstallForAllUsers. -Property replaces that selection and accepts only AcquisitionIdentity, AutoUpdateSetting and CanInstallForAllUsers (duplicates are read once, in first-selection order). Numeric aliases, wildcards and All are rejected before any getter is invoked.

Privacy: AcquisitionIdentity is neither probed nor read by default. It is returned only with an explicit -Property AcquisitionIdentity selection, alone or in a list. Nothing writes its value to verbose, debug or information output. The null unselected identity is omitted by System.Text.Json; its availability remains Unknown. Default error rendering omits raw native messages, while the original diagnostic exception and typed metadata remain available in the ErrorRecord for deliberate inspection. Treat explicitly requested identity and native diagnostic messages as sensitive.

Property Scope and interpretation
AcquisitionIdentity ManagerContext: identity associated with installs on the supplied manager. No verified account/SID mapping or persistent user/global setting is inferred. Cross-manager persistence is not established.
AutoUpdateSetting Device: documented device-wide app auto-update setting, including policy-controlled values. Independent context/manager objects do not isolate device settings or establish a persistent per-user preference.
CanInstallForAllUsers CallingProcess: get-only privilege observation, not a privilege grant, capability authorization, proof that installation is available or guarantee of success.

An AppInstallSettingsSnapshot contains ContextId (local correlation, never a SID or native install ID), UserScope = Caller, per-property scope, RequestedProperties, and successfully ReadProperties. Acquisition identity has a separate availability and nullable string. AutoUpdateSetting uses AppInstallValue<int> to retain the native enum code, including unknown future codes: 0 Disabled, 1 Enabled, 2 DisabledByPolicy, 3 EnabledByPolicy. CanInstallForAllUsers uses AppInstallValue<bool>.

Unselected values are Unknown; selected members absent from runtime metadata are Unavailable without activation or invocation for that member. Available false/zero and an explicitly requested empty identity remain real observations. A missing member may coexist with other successfully read values. Platform, lifetime, runspace, activation and getter errors terminate without a partial snapshot; access denial is never false/empty/unavailable success. Original exceptions, HRESULTs, source getter and availability/activation/invocation phase are retained. Activation failure is still cached by the context.

Each selected getter uses the existing availability/lifecycle boundary. These three getters are synchronous: no async operation or wait is created, and only the short getter runs under the context lock. The returned snapshot is a sequential, detached observation, not an atomic settings transaction. Reusing the context rereads the values rather than caching observations. Dispose the context in finally; module removal does not end its caller-owned lifetime. The settings reader performs no setter, identity change, user override, entitlement, installation, search or queue-control operation.

Request-AppInstallUpdateSearch -Context $context -CorrelationVector $correlationVector -ClientId $clientId implements only SearchForAllUpdatesAsync(string correlationVector, string clientId, AppUpdateOptions). All three parameters are mandatory; correlation/client strings must be nonempty and non-whitespace and are forwarded unchanged. No client identity, acquisition identity, catalog, account or user override is invented. These inputs are not authorization or a way to bypass capability restrictions.

This is a queue mutation. Both writable safety properties are explicitly set false: AutomaticallyDownloadAndInstallUpdateIfFound and AllowForcedAppRestart. The documented false value still adds discovered updates to the install queue paused. High-impact ShouldProcess confirmation describes that side effect. -WhatIf and declined confirmation perform no native metadata probes, activation, options construction or search, and return no success result. There is no read-only-search switch, per-app selection, ForUser, custom catalog, automatic-action switch or alternate-overload fallback.

After confirmation the coordinator checks required types, method arity, writable safety properties and required item/status members before activation, constructs and configures options, then submits through the context’s short-call lifecycle boundary. Waiting stays outside the context lock on the execution thread. Optional item/status fields keep inventory’s per-member availability semantics. The same live owning context is required; it is not disposed by this command.

One immutable AppInstallRequestSnapshot is emitted only after the search, operation cleanup and complete item capture succeed, including an available empty result. Acceptance = Accepted means an async handle was returned; OperationState = Completed means search completion, not installation completion. Returned items can be paused/nonterminal or have unknown status. Native item state, percentage, staging and launch readiness do not redefine request acceptance or search completion.

RequestId is a per-invocation local GUID, separate from ContextId, projected item/parent identities and the caller’s native CorrelationVector/ClientId. No value is a synthesized native installation ID or verified SID. These three new request fields are nullable for older snapshots; the prior constructor and older JSON remain compatible. Default request formatting (including PowerShell deserialized requests while the module’s view is loaded) displays local IDs, API/scope/outcome fields and item count, not CorrelationVector, ClientId, item payloads or raw errors. Direct property access, Format-List * and JSON retain the original values for explicit inspection. Hiding fields in a default view is not redaction, secret storage or a security boundary.

Children are captured when available, de-duplicated by projection identity and retain parent/context/caller scope. Partial search results merge into the bounded 4096-entry identity cache, preserving unrelated items and existing local IDs. Overflow fails atomically without pruning; full inventory scans retain their existing pruning behavior.

Failure produces a terminating ErrorRecord whose TargetObject is the typed request (not a successful pipeline result). It retains acceptance, last observed native state, local wait state, original error/HRESULT/source/phase and secondary cleanup errors. Pre-submission failures are NotSubmitted; an exception during submission is Unknown, since remote rejection/rollback cannot be proved. Errors or failed capture retain ItemsAvailability = Unknown with no partial list. Raw native messages and caller correlation values are not rendered by default; deliberate inspection of error records/snapshots can expose them.

StopProcessing cancels only the per-command local wait token. There is no native Cancel, pause/resume/control call or rollback. The adapter closes terminal operations and releases pending ones without canceling them. Waiting can end as StoppedLocally while acceptance is Accepted and native state is Started or unknown. PowerShell may suppress all result/error writes once a pipeline is stopped, so absence of output is never evidence of no submission. There is no hard timeout for synchronous WinRT calls.

Only prior empty native-search evidence supports the scoped development decision; grouped/nonempty capture, confirmation and cancellation are tested with fail-closed fakes. No live Store actions are exercised by these tests. #233 remains open: private-capability restrictions still apply, and this does not deliver the broader #244 family or guarantee third-party support.

Bounded exact-item observation

Wait-AppInstallItem -Context $context -LocalItemId $localItemId -TimeoutSeconds 10 requires one live creating-runspace caller context and one exact local ID retained by its successful inventory/search capture. Stale/unresolvable IDs, wrong runspaces, disposed contexts and overlapping observations fail before subscription. No ProductId/PackageFamilyName fallback, per-item events, group wait, multiple-target selection, hidden manager, manager-wide following or ForUser is provided.

Only manager ItemStatusChanged and ItemCompleted are subscribed, after both members pass availability gates. Callbacks only set bounded invalidation flags; they never inspect sender/event payload properties, read native state or call PowerShell. A notification for another item can cause a selected-item reread; reason flags name manager invalidation, not selected-item events. Duplicate notifications coalesce into one pending slot, not a lossless event queue. A generation overflow errors rather than silently losing invalidation.

Subscriptions precede the initial snapshot. Every detached capture runs on the cmdlet execution thread using inventory’s existing status/availability/HRESULT policy. A delivered-generation fence discards captures invalidated during reading; terminal capture closes callback acceptance at that local fence. This is not a native atomicity, ordering, notification-latency/loss or terminal-state permanence guarantee. Local observation sequence reflects captures, never native event order.

The command emits one immutable AppInstallMonitorResult only after successful cleanup. It contains ContextId, LocalItemId, Caller scope, local Outcome and up to 64 observations (sequence, elapsed time, reason flags and detached item snapshot). There is no progress output or intermediate success stream. The mandatory TimeoutSeconds range is 1-30, measured monotonically from before lease acquisition; synchronous getters/add/remove calls can exceed it. Too many snapshots fail rather than truncate. TimedOut does not mean failure/cancellation of installation. TargetTerminal requires the existing observed native state/HRESULT policy, and can mean success, failure or native cancellation. Mere completion notification, 100 percent, staging, launch readiness and async search completion do not suffice. Unknown states/unavailable evidence remain unknown.

An already-terminal target is still subscribed/captured/cleaned up. Children are not enumerated; GroupOutcome = NotEvaluated, including when a parent succeeds. The lease pins one observed projection, not queue membership: disappearance is not inferred from manager events or a missing callback. A getter that fails after removal preserves its source/error/HRESULT, never an empty/success fallback. Monitoring performs no additional collection scan or cache commit, so full inventory pruning and bounded partial-search union semantics are preserved. An active lease can retain its exact projection after cache pruning; a subsequent new observation of the old ID cannot resolve it.

Cancellation, Ctrl+C and context shutdown stop observation only, never queue Cancel/pause/restart/search or automatic actions. Cleanup closes callback acceptance, unsubscribes every acquired token in reverse order outside context/callback locks, and releases the observation lease last. Context disposal prevents further use and signals the active lease without waiting; actual manager release is deferred until the last lease exits. The command never disposes its caller context. An unsubscribe exception means native detachment is unproven; all remaining cleanup is attempted. Primary HRESULT and every secondary cleanup failure are retained, and cleanup-only failure is not a successful result. Stopped pipelines may suppress error/output. Default formatting omits item/error payloads and raw native diagnostics; explicit inspection and JSON retain them and must be treated as sensitive.

Limited manager-event access was observed separately; individual-item event access, nonempty exact-item native status/lifetime behavior, groups, callback ordering and support guarantees remain unverified. This implementation is validated with fail-closed fakes, not additional live Store operations. AppInstall stays unreleased while #233 official support is unresolved. No privilege/capability workaround is provided.

Async and event integration seams

The internal async adapter accepts an already-created WinRT operation; it does not submit one. The waiter polls native completion state on the execution thread and preserves exceptions returned by GetResults. Stopping the local wait uses a separate cancellation token and does not call native Cancel. Disposing an adapter closes only terminal operations; a still-started operation is released without cancellation. There are no polling tasks or completion callbacks left running in the module after a wait ends.

Future command implementations should use the owning WaitAndDispose boundary outside Use, then write a result only after both the wait and cleanup succeed. It translates operational native failures to AppInstallError, preserving the primary exception/HRESULT and any secondary Status/Close cleanup failure. A cleanup-only failure produces an error, not a successful result. On failure, the internal AppInstallOperationException.Error.ToErrorRecord() retains the original exception and puts the typed metadata in TargetObject; it does not write to PowerShell itself. StopProcessing should cancel only the local wait token. No implicit native cancellation or queue-control action is provided.

Failure preservation is independent of the operational translation policy. The owning boundary captures every primary and cleanup exception solely to preserve/rethrow failures, never to return a fallback result. An untranslated failure with successful cleanup is rethrown with its original instance and stack. If it also has a cleanup failure, AppInstallCleanupException retains both original exceptions in order, the primary HRESULT, source operation and both phases without classifying the primary as native. A translated primary keeps any unclassified cleanup in CleanupErrors with kind UnclassifiedFailure. An unclassified cleanup-only failure propagates unchanged. In particular, exception type alone cannot prove that a null-reference or invalid-cast failure came from native code rather than a managed bug.

The injectable event subscription owns its unsubscribe resource. Callbacks only signal invalidation; future monitoring must read snapshots and call PowerShell pipeline writers on the cmdlet execution thread. Repeated notifications can coalesce. Wait-AppInstallItem implements only manager-event invalidation; individual-item event subscriptions remain unverified and are not implemented.

Request acceptance, async-operation completion, successful installation, IsStaged, and ReadyForLaunch are different observations. None is inferred from a context, a successful activation, or mere method-name presence.

Immutable snapshot contracts

All snapshot types live in Shmuelie.Windows.AppInstall. Constructors perform no native access. Get-only properties and copied, read-only collections prevent caller mutations of the input lists from changing a snapshot or its descendants. These are data contracts for dependent commands, not additional exported operations.

Contract Meaning
AppInstallValue<T> A nullable scalar and explicit Unknown, Available, or Unavailable availability. Available false/zero is different from unknown/unavailable.
AppInstallItemIdentity Observed ProductId/PackageFamilyName, explicit caller/unknown user scope, and local ContextId/LocalItemId/ParentLocalItemId correlation.
AppInstallItemSnapshot Identity, status, and copied children with their own availability. Available empty children are distinct from children not observed or unavailable.
AppInstallStatusSnapshot Observed native state code, byte counts, percentage, IsStaged, ReadyForLaunch, explicit terminal observation and error.
AppInstallRequestSnapshot Separate request acceptance, native operation state, local wait state and returned-item availability, with nullable local RequestId and caller-provided native correlation strings. No installed-success shortcut.
AppInstallEntitlementSnapshot Explicit caller/device/unknown entitlement scope, observed native status and grant observation. No grant is inferred from native code zero or object construction.
AppInstallError Source operation, failure phase/kind, original HRESULT, exception type/message, and copied cleanup failures.
AppInstallSettingsSnapshot Caller context correlation, property scopes, copied requested/read property lists and only the selected settings observations; acquisition identity is opt-in.

Unknown means not observed; Unavailable means the caller established that the value cannot be obtained in this context/version. A missing member must not be replaced with a successful-looking zero or empty inventory. Native integer enum codes are preserved even when newer than the module’s knowledge. Future adapters must map a terminal state from actual installation evidence, not from percentage, request completion, staging, launch readiness or an entitlement result.

Local item IDs remain stable while the same projected identity stays in the bounded cache, refreshed by full inventory scans and augmented by partial search results. They are not native IDs, are not derived from a product/account/SID, and must not be reused to target a different item. The inventory adapter owns that bounded projection-identity-to-local-ID mapping. Serialized snapshots are detached observations, not native handles or authorization to perform later queue actions. Product/family identifiers are preserved verbatim, not fabricated from context IDs. AppInstallStatus.User is not projected into a SID or account name; that mapping and broader user scopes remain unverified.

Request Accepted may coexist with native Started and local StoppedLocally. Native Completed reports only the API operation completion; the returned items can still have unknown/nonterminal installation states. IsStaged is the native restart-pending observation, and ReadyForLaunch can be true before installation has finished. These fields never change one another.

System.Text.Json round-trips the get-only scalar, identity, group, request, entitlement and error metadata, including collection copies. AppInstallError retains the original exception reference in-process (an exception itself is a mutable diagnostic object); its captured metadata is immutable. JSON deliberately omits that reference. Deserialized metadata cannot be converted back into a live-native ErrorRecord, and does not synthesize an exception pretending to be the original. Nothing automatically logs identities, snapshots or native messages.

API and options matrix

New-AppInstallContext (#234), Get-AppInstallItem (#236) and Get-AppInstallSettings (#238) and only the caller all-app paused Request-AppInstallUpdateSearch (#244 subset), plus bounded Wait-AppInstallItem (#239), are implemented here but remain unreleased. Names below for other work items are proposed naming conventions, not commands available to invoke. Later commands use an explicit -Context, singular nouns and approved PowerShell verbs. Mutating commands must use ShouldProcess; -WhatIf must submit no request. Read-style verbs must not conceal queue mutations.

Observed means bounded runtime evidence for a particular call, not a support guarantee. Cleared later still requires its dependent implementation PR. Gated means unverified/unapproved for this scoped foundation. All counts below refer to documented manager members; overloads are grouped by exact method name. The minimum Windows target of this module remains build 19041; per-member and method-parameter-count checks are still required before invocation.

Manager properties (5)

Member Planned surface Evidence / delivery scope
AppInstallItems Get-AppInstallItem -Context Caller-scoped inventory implemented in #236. Getter/count observed previously; nonempty item/status paths are covered by deterministic fakes, not live support claims.
AppInstallItemsWithGroupSupport Get-AppInstallItem -Context -IncludeChildren Grouped inventory implemented in #236. Getter/count observed previously; group/child paths have fake coverage only. Added in build 15063.
AcquisitionIdentity Get-AppInstallSettings -Context -Property AcquisitionIdentity; future Set-AppInstallSetting Getter implemented in #238, exact opt-in only; omitted by default. Setter remains gated in #240; no identity spoofing or implicit account/SID interpretation.
AutoUpdateSetting Get-AppInstallSettings -Context; future Set-AppInstallSetting Getter implemented in #238 and selected by default. Device-setting write gated in #240; independent contexts do not isolate device settings.
CanInstallForAllUsers Get-AppInstallSettings -Context Getter implemented in #238 and selected by default. Read-only in the C# signature (despite the reference summary saying “gets or sets”), added in build 17763. Not an authorization grant or guarantee of installation availability/success.

Manager methods (23 families)

Member Planned surface / overload distinctions Evidence / delivery scope
Cancel Stop-AppInstallItem -Context; product, optional telemetry overload Gated #246; exact target and group impact must be explicit.
GetFreeDeviceEntitlementAsync Request-AppInstallEntitlement -Scope Device Gated #237; grants to device users, not a read-only query.
GetFreeUserEntitlementAsync Request-AppInstallEntitlement -Scope Caller Gated #237; grant operation, not a read-only query.
GetFreeUserEntitlementForUserAsync Future explicit-user entitlement variant Gated #237 and user-scope validation; no ForUser binding here.
GetIsAppAllowedToInstallAsync Test-AppInstallPolicy; basic and telemetry overloads Gated #235; method-name presence does not prove policy-query access.
GetIsAppAllowedToInstallForUserAsync Future explicit-user policy variant Gated #235 and user-scope validation.
GetIsApplicableAsync Test-AppInstallApplicability Gated #235.
GetIsApplicableForUserAsync Future explicit-user applicability variant Gated #235 and user-scope validation.
GetIsPackageIdentityAllowedToInstallAsync Test-AppInstallPolicy package-identity parameter set Gated #235; added in build 17134.
GetIsPackageIdentityAllowedToInstallForUserAsync Future explicit-user package-policy variant Gated #235 and user-scope validation; added in build 17134.
IsStoreBlockedByPolicyAsync Test-AppInstallPolicy Store-policy parameter set Gated #235.
MoveToFrontOfDownloadQueue Move-AppInstallItem -Context Gated #243; exact target, queue mutation.
Pause Suspend-AppInstallItem -Context; product, optional telemetry overload Gated #241; group impact must be explicit.
Restart Resume-AppInstallItem -Context; product, optional telemetry overload Gated #242; resume/restart request is not installation completion.
SearchForAllUpdatesAsync Request-AppInstallUpdateSearch -Context -CorrelationVector -ClientId; no-argument, telemetry-only, and options overloads are distinct Only caller-scoped three-argument options overload with both safety flags explicitly false is implemented (#244 subset). High-impact ShouldProcess; found updates can be queued paused. Other overloads and automatic-update variants remain gated.
SearchForAllUpdatesForUserAsync Future explicit-user all-app search; telemetry/options overloads Gated #244 and user-scope validation, including false-flag variants.
SearchForUpdatesAsync Future per-app update search; basic/telemetry/options overloads Gated #244; caller all-app evidence does not authorize per-app variants.
SearchForUpdatesForUserAsync Future explicit-user per-app update search Gated #244 and user-scope validation.
StartAppInstallAsync No new command or fallback Retired, including basic and telemetry overloads. Do not use as the default or an automatic fallback.
StartProductInstallAsync Start-AppInstall -Context; options and older boolean/volume overloads Gated #245. Prefer the options overload once approved; after first sign-in, not during OOBE.
StartProductInstallForUserAsync Future explicit-user product install Gated #245 and user-scope validation; after first sign-in, not during OOBE.
UpdateAppByPackageFamilyNameAsync Request-AppInstallUpdate -Context; basic/telemetry overloads Gated #247; submits an update rather than merely discovering it.
UpdateAppByPackageFamilyNameForUserAsync Future explicit-user package-family update Gated #247 and user-scope validation.

Manager events (2)

Member Planned surface Evidence / delivery scope
ItemCompleted Wait-AppInstallItem -Context -LocalItemId -TimeoutSeconds Limited manager-event access observed; implemented as payload-free invalidation only. Not selected-item identity or terminal-success evidence.
ItemStatusChanged Wait-AppInstallItem -Context -LocalItemId -TimeoutSeconds Owned manager subscription with bounded coalescing, execution-thread exact-item snapshots and local cancellation only. Individual-item events and group waiting remain gated.

AppUpdateOptions (3)

Member Planned binding / safety contract Delivery scope
AutomaticallyDownloadAndInstallUpdateIfFound Fixed false in the implemented caller all-app path; no true switch Added in build 17763. False still adds found updates to the install queue in a paused state. It is not a read-only search. Only #244’s approved subset; broader behavior gated.
AllowForcedAppRestart Fixed false in the cleared caller all-app path Added with options in build 17134. No implicit forced-restart consent. True and broader variants remain gated.
CatalogId Future explicit catalog option where applicable No implicit catalog override in the cleared subset; per-app/custom catalog behavior requires its own validation.

No real update search is run by foundation tests, including false-flag searches. The #244 subset uses ShouldProcess because finding updates can queue work. The options object must be fully configured before submitting the approved call; omitting an option is not equivalent to explicitly setting it false.

AppInstallOptions (15)

All bindings below are planning only for gated #245. The options type was added in build 17134; later members still require availability checks.

Member Planned binding / safety contract Delivery scope
AllowForcedAppRestart Explicit restart consent; never inferred Gated #245
CampaignId Explicit documented campaign value, no hardcoded caller identity Gated #245; build 17763
CatalogId Explicit catalog value where supported Gated #245
CompletedInstallToastNotificationMode Explicit notification choice Gated #245; build 17763
ExtendedCampaignId Explicit documented campaign value Gated #245; build 17763
ForceUseOfNonRemovableStorage Explicit storage-policy override Gated #245
InstallForAllUsers Explicit all-user consent and separately validated access Gated #245; build 17763. No elevation or capability workaround provided.
InstallInProgressToastNotificationMode Explicit notification choice Gated #245; build 17763
LaunchAfterInstall Explicit launch consent Gated #245
PinToDesktopAfterInstall Explicit pinning consent Gated #245; build 17763
PinToStartAfterInstall Explicit pinning consent Gated #245; build 17763
PinToTaskbarAfterInstall Explicit pinning consent Gated #245; build 17763
Repair Explicit repair request, not normal-install inference Gated #245
StageButDoNotInstall Explicit staging-only request; not completed installation Gated #245; build 17763
TargetVolume Explicit typed package-volume selection Gated #245; no silently substituted volume

AppInstallItem.ProductId, PackageFamilyName, InstallType, IsUserInitiated, Children, ItemOperationsMightAffectOtherItems and GetCurrentStatus feed #236’s immutable snapshots. AppInstallStatus.InstallState, BytesDownloaded, DownloadSizeInBytes, PercentComplete, ErrorCode, IsStaged and ReadyForLaunch must retain independent observations and member availability. The User object remains unexposed until its identity/scope semantics are validated; no fabricated Windows.System.User or SID is supplied.

Item Completed/StatusChanged events belong to gated #239. Item Cancel/Pause/Restart overloads remain gated along with the corresponding manager controls. LaunchAfterInstall, notification and pinning properties do not authorize implicit setting writes; they stay in the separately reviewed install/settings families. Inventory does not materialize or invoke those mutating native members.

Caller-scoped inventory

Get-AppInstallItem -Context $context [-ProductId <string[]>] [-PackageFamilyName <string[]>] [-IncludeChildren]

The context must be live and belong to the current runspace. Inventory activates its manager lazily, then reads one of the two caller-scoped collections. Each native member read is a short Use invocation with an exact availability check; there is no subscription, user override, search, update, entitlement, or control request. Native getter failures preserve the original exception, HRESULT, phase and source member in the PowerShell error record.

Identity getters and GetCurrentStatus are required. Optional item/status properties absent from metadata are Unavailable and are not called. A native getter that throws, including access denial or a disappeared item, is an error, not Unknown/Unavailable. Results are buffered: a failed capture emits none. A successful empty queue or unmatched filter emits no objects. Earlier results from a separate pipeline context/capture remain valid historical observations. Native reads are not a single atomic transaction and state may change afterward.

AppInstallItemSnapshot additionally exposes availability-qualified InstallType, IsUserInitiated, and ItemOperationsMightAffectOtherItems. Status exposes availability-qualified HResult, alongside the existing independent fields. ErrorCode returned as an exception is installation-status data, distinct from a getter throwing. The supported C#/WinRT projection uses null for a successful HRESULT; inventory represents that as zero. Non-failing HRESULT distinctions not retained by that projection are not reconstructed through raw ABI calls.

Known native Completed with an observed non-failure HRESULT is terminal Succeeded; native Error and Canceled have their own terminal observations. Other known states remain NotTerminal, and future unknown state codes remain Unknown while the integer code is preserved. Completed without an observed non-failure HRESULT remains conservatively Unknown. PercentComplete, IsStaged, ReadyForLaunch and presence in the queue do not imply success.

Filters are ordinal case-insensitive exact matches. Alternatives within one filter use OR; different filters use AND; wildcard characters are literal. Filtering occurs after the full read/validation, so an unrelated unreadable item is not silently hidden by a filter. Distinct projected identities with the same product/family still return distinct local IDs rather than choosing an ambiguous control target.

Grouped mode reads Children, deduplicates repeated references under the same parent, and removes top-level aliases of a known child. Conflicting parents or cycles fail explicitly. Matching parents retain complete subtrees; matching descendants of unmatched parents retain their parent-local ID. The default ungrouped view leaves child availability Unknown and does not invent parents. No status User/account/SID getter is called. Caller scope describes the chosen API context, not a verified account identity for every returned item.

The context’s manager owns a cache keyed by supported projection equality, which AppInstallItem implements. Strong references are retained only for the last successful captured graph, bounded to 4096 distinct items and 128 group levels. A successful later capture prunes missing identities; failed captures do not grow or replace the cache. Context disposal clears it. Switching views can prune items not visible in the chosen view; an item returning after pruning gets a fresh local ID. This is neither a universal native install ID nor permission to use a deserialized snapshot for controls.

Snapshots are ordinary immutable CLR values. JSON retains their nested structure; CSV consumers can select scalar fields explicitly, for example:

Get-AppInstallItem -Context $context |
    Select-Object @{n='ProductId';e={$_.Identity.ProductId}},
                  @{n='PackageFamilyName';e={$_.Identity.PackageFamilyName}},
                  @{n='NativeState';e={$_.Status.NativeInstallState.Value}},
                  @{n='HResult';e={$_.Status.HResult.Value}}

No native nonempty item/status/group calls were executed during implementation. Those paths, source/packaged command execution, duplicate/cycle/error behavior and serialization are validated with fail-closed injected adapters. The official private-capability restriction and limited native evidence remain unchanged.

Sources