Classic shell integration is declarative in the registry: an application writes a verb under a file class, or registers a COM handler, and the shell reads those keys when building a menu. Anything that can read the registry can enumerate it.
Packaged applications work differently. An MSIX or Store package declares its context menu commands inside its application manifest, as part of the package identity. At install time those declarations are registered into a dedicated packaged-COM catalogue rather than written as ordinary class registrations. The shell resolves them through that catalogue. The consequence is that there is no conventional key to find, no command line to read, and no obvious path from the visible menu entry back to a registry location.
Enumerating them therefore requires a different approach: list the installed packages, read each manifest, extract the declared commands along with their identifiers and the file types they apply to, and then cross-reference the packaged-COM catalogue to confirm what is actually registered. ContextCleaner does this, and it handles a detail that trips up naive parsers — the manifest element namespace varies between package generations, so matching on a fully qualified name misses entries from packages built against a different schema version. Matching on the local element name instead catches all of them.
Disabling a packaged command uses the same mechanism Windows provides for COM handlers: the command identifier is added to the shell extensions block list. This is a machine-wide setting, which is why disabling a modern-menu entry needs administrator approval where a per-user classic entry does not. ContextCleaner collects every machine-wide operation in a batch into a single elevation prompt per apply, so a cleanup pass touching a dozen packaged commands asks once rather than a dozen times. There is a deliberate implementation note behind this: the per-user variant of that block list reports success when written but the shell ignores it, so writing there would produce a silent no-op — a change that appears to work and does nothing.
Because the block list is keyed by identifier and the package itself is untouched, the operation is fully reversible and the application remains installed and functional.