There is no documented public, non-mutating API that authoritatively classifies a named AppContainer profile as existing, absent, incomplete, or inaccessible; use CreateAppContainerProfile as the atomic lifecycle operation, and regard the returned S_OK as the evidence that this invocation created the profile.
1. Profile existence and enumeration
DeriveAppContainerSidFromAppContainerName is deterministic identity derivation. Its documented successful result means that Windows derived a SID from a valid name; its contract does not document profile existence or absence semantics.^1^
The other public APIs do not provide a complete existence test either:
-
GetAppContainerFolderPathreturns a profile folder path, not a profile-state record. -
GetAppContainerRegistryLocationoperates on the current profile and has no profile-name or package-SID argument, so it cannot query an arbitrary candidate profile.^2^ - Undocumented HKCU mapping keys are not a supported contract and cannot reliably distinguish absence, partial state, access denial, or implementation changes.
- A folder’s presence or absence is likewise not authoritative for the complete profile.
NetworkIsolationEnumAppContainers enumerates created AppContainers and returns structures containing the AppContainer SID, user SID, and name.^3^ ^4^ It can therefore provide supplementary positive evidence, but its documentation does not define absence from the result as authoritative proof that a particular Userenv profile does not exist, nor does it promise classification of incomplete or inaccessible profiles.
NETISO_FLAG_FORCE_COMPUTE_BINARIES only ensures current and complete binary information before each entry is returned. It does not document a registration refresh, synchronization barrier, or stronger absence guarantee.^3^
2. Meaning of GetAppContainerFolderPath returning 0x80070002
The documented GetAppContainerFolderPath contract specifies:
-
S_OKon success; -
E_INVALIDARGfor a null SID-string or output-pointer argument; - selection of the user context from the thread token, or otherwise from the process identity.^5^
It does not document HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) as meaning “profile absent,” “registration missing,” or “profile incomplete.” 0x80070002 generally means that a file or resource required by that operation could not be found, but it is not by itself a component-specific diagnosis.^6^
Consequently, your observed result establishes only this:
- no path was returned in the effective token context;
- the call failed because some required object or resource was not found;
- the public contract does not expose which internal dependency was missing.
It cannot safely be converted into an Absent state. Also ensure lifecycle calls run under the intended user token: thread impersonation changes which user GetAppContainerFolderPath uses.^5^
3. Safe creation and ownership tracking
Call CreateAppContainerProfile directly and branch on its documented result:
-
S_OK— this invocation created the current user’s data store and returned its SID. -
HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)— the data store pre-existed; do not adopt it for rollback or delete it. -
E_ACCESSDENIED— the caller lacks permission. - Any other failure — do not record ownership and do not delete based merely on derived SID or filesystem observations.
A profile contains per-user/per-app folders and registry storage. Creation applies to the current user unless the caller impersonates another user.^7^
Keep an in-memory transaction record similar to:
bool createdByThisOperation = false;
IntPtr returnedSid = IntPtr.Zero;
int hr = CreateAppContainerProfile(name, displayName, description,
IntPtr.Zero, 0, out returnedSid);
if (hr == 0) {
createdByThisOperation = true;
// Compare returned SID with the independently derived SID.
} else if (hr == HRESULT_FROM_WIN32_ERROR_ALREADY_EXISTS) {
// Existing profile: never mark owned and never roll it back.
} else {
Marshal.ThrowExceptionForHR(hr);
}
After S_OK, supported verification can include:
- validate and retain the returned SID;
- derive the SID from the same moniker and compare it with the returned SID;
- call
GetAppContainerFolderPathusing the returned SID string; - retain the exact profile name, current-user identity, capability set, and every application-owned child resource.
These checks detect inconsistencies, but they do not enumerate every registry and filesystem resource created internally. The supported success guarantee is that S_OK means the data store was created successfully.^7^
4. Safe rollback and deletion
Delete only when all of these are true:
- The same operation received
S_OKfromCreateAppContainerProfile. - No
ERROR_ALREADY_EXISTSpath was taken. - The exact creation name and intended user context were retained.
- All processes launched under that profile have exited.
- All application-owned file and registry handles associated with its storage are closed.
Then call DeleteAppContainerProfile under the same user context. It deletes the current user’s named profile; deleting another user’s profile requires impersonating that user.^8^
Important limitations:
- Deleting a nonexistent profile also returns success, so
S_OKdoes not prove that something previously existed. - Open storage handles can prevent complete storage removal.
- If deletion fails, the profile state is documented as undetermined; call
DeleteAppContainerProfileagain to complete the operation. - No documented public API determines whether arbitrary processes are currently using the profile. Usage safety must come from controlling and joining your own child processes and closing your own handles.
- Neither post-delete folder failure nor absence from network enumeration is documented as an authoritative complete-removal check.
Therefore, the strongest defensible rollback statement is: a profile for which this operation received creation S_OK was passed to the supported deletion API after owned processes and handles were closed. The public contracts do not support asserting that every internal registration, registry key, and storage object was independently enumerated and verified absent.
References
- DeriveAppContainerSidFromAppContainerName function (userenv.h)
- GetAppContainerRegistryLocation function (userenv.h)
- NetworkIsolationEnumAppContainers function (networkisolation.h)
- INET_FIREWALL_APP_CONTAINER structure (networkisolation.h)
- GetAppContainerFolderPath function (userenv.h)
- 0x80070002 Error code - Microsoft Q&A
- CreateAppContainerProfile function (userenv.h)
- DeleteAppContainerProfile function (userenv.h)