A desktop monitor displays C++ code and a diagram showing a packaged Windows app being activated via COM.
Launching a packaged Windows app from code takes one COM call, once you know the app's AUMID. Microsoft's Inside MSIX blog, in a post by principal software engineer Howard Kapustein, walks through that call and builds a small launcher, StartApp.exe, in C, C++ and C#. This article covers the AUMID format, the API's behavior, the three implementations and the pitfalls.

A desktop monitor displays C++ code and a diagram showing a packaged Windows app being activated via COM. What an AUMID is and how it is built​

An Application User Model ID (AUMID) identifies a packaged app. It combines two parts:

  • Package family name: built from the package name and the publisher identity.
  • Package Relative Application Id (PRAID): the Id attribute of the <Application> element in AppxManifest.xml.

The two are joined with an exclamation mark: <PackageFamilyName>!<PRAID>.

Microsoft's AppListEntry documentation says the AUMID is independent of package version or architecture, so it can identify an app across versions and platforms. That separates it from the package full name.

Kapustein's example uses a made-up package, Contoso.PointOfSale:

ItemValue
Package full nameContoso.PointOfSale_1.2.3.4_x64__eh4htm4n7tdre
Publisher IDeh4htm4n7tdre
Package family nameContoso.PointOfSale_eh4htm4n7tdre
PRAIDCardReader
AUMIDContoso.PointOfSale_eh4htm4n7tdre!CardReader

The full name carries the version (1.2.3.4) and architecture (x64). The family name and AUMID do not. These values are illustrative, not data from a real package.

Developers don't have to concatenate the strings by hand. Microsoft documents FormatApplicationUserModelId, which builds an AUMID from a family name and PRAID. It also documents ParseApplicationUserModelId, which splits one back apart. Both use the usual two-call pattern: query the required buffer size, then supply a buffer. Both require Windows 8.1 or Windows Server 2012 R2 or later.

The activation call​

Microsoft's documentation says ActivateApplication activates the specified Windows Store app for the generic launch contract (Windows.Launch) in the current session. It takes four parameters:

  1. The AUMID.
  2. An optional, app-specific argument string.
  3. An options flag.
  4. An output pointer that receives the process ID of the app instance that fulfills the launch contract.

It returns S_OK on success and an HRESULT error otherwise. The minimum client is Windows 8, desktop apps only. The minimum server is Windows Server 2012.

You get the interface by calling CoCreateInstance with CLSID_ApplicationActivationManager. Microsoft says not to implement the interface yourself.

Activation options​

All three sample programs pass AO_NONE, which sets no flags. The other documented flags are:

  • AO_DESIGNMODE: for design tools, and it needs debug mode enabled on the package.
  • AO_NOERRORUI: suppresses the error dialog if the app fails to activate.
  • AO_NOSPLASHSCREEN: hides the splash screen. Microsoft warns that without debug mode enabled, the PLM will terminate the app after a few seconds.
  • AO_PRELAUNCH: prelaunch mode, supported starting in Windows 10.

The three StartApp.exe versions​

C​

The minimal version is a plain COM client:

  • It rejects a null or empty AUMID, and a null process-ID pointer, with E_INVALIDARG.
  • It creates the activation manager in-process and calls ActivateApplication.
  • It releases the interface and returns the HRESULT.
  • Its wmain initializes COM in a single-threaded apartment, then prints either the PID or the hexadecimal error code.

C++ with WIL​

The second version uses the Windows Implementation Library (WIL). It replaces manual cleanup with wil::CoCreateInstance and replaces manual HRESULT checks with THROW_IF_FAILED. It also adds parameter passing, by joining the extra command-line tokens with spaces. The author states that this does not handle backslashes, quotes and spaces properly and leaves that "as an exercise for the reader". Treat it as a demo, not a production launcher.

C​

The C# version declares the COM interface itself with [ComImport] and GUID attributes. It uses Marshal.ThrowExceptionForHR for error handling, and it joins arguments the same way as the C++ version. The GUIDs it uses are 45BA127D-10A8-46EA-8AB7-56EA9078943C for the interface and 2E941141-7F97-4756-BA1D-9DECDE894A3D for the class. Community samples on Microsoft Q&A and elsewhere declare the same interface and CLSID, so the declaration is a common pattern.

Practical caveats​

  • Argument strings are app-specific. Microsoft's wording means each app decides what the string means. Don't assume a universal convention. Community examples exist for apps that read arguments, such as one that opened a Settings page with a page= argument. Those are third-party snippets, not guarantees.
  • The process lifetime matters. Microsoft notes the activation manager creates a thread in its host process to serve the activation event arguments. For a long-lived caller, in-proc creation is fine. A caller that exists only to launch the target should instead use CLSCTX_LOCAL_SERVER, which creates the object in Dllhost.exe. The samples use CLSCTX_INPROC_SERVER, which is fine for a demo but worth reconsidering for a short-lived launcher.
  • An AUMID names a package-level app, not an instance. A GitHub issue in a third-party project shows the consequence. A developer used ActivateApplication to bring a window forward, but could not choose between two running instances of the same packaged app. The reported fix was to switch to process-ID-based window handling for that purpose. That is one project's experience, not Microsoft guidance. Still, it matches the API's design: the process ID is an output, not an input.
  • A valid AUMID does not guarantee success. The app must be installed for the user, and activation can fail with an HRESULT.

Alternatives and what comes next​

Microsoft also documents a Windows Runtime route. AppListEntry exposes an app's AUMID, and the documentation's sample finds a matching entry and calls LaunchAsync(). It is a different API path with a different baseline: it needs Windows 10 Fall Creators Update (10.0.16299.0). IApplicationActivationManager remains the lower-level option that works from plain Win32 code.

The post also covers a command-line gap. Kapustein says Windows doesn't include a utility like StartApp.exe for activation by AUMID. A shortcut can be defined programmatically in the Start menu to launch a packaged app by AUMID. He also says File Explorer's New > Shortcut won't accept an AUMID directly. That claim comes only from the post and I haven't verified it independently. The post promises options for command-line activation in the next installment, which hasn't been covered here. I'm not claiming any workaround beyond what the post states.

Why it matters for IT and developers​

Anyone automating around MSIX or Store-packaged apps runs into this. Examples include test harnesses, kiosk launchers, deployment scripts and tools that only know how to start executables. The AUMID is the stable handle across app updates, because it doesn't change with version or architecture. Combined with Microsoft's format and parse functions and the three reference implementations, the post gives a clear starting point, provided you handle argument quoting properly.

 

References

  1. IApplicationActivationManager::ActivateApplication (shobjidl_core.h) - Win32 apps | Microsoft Learn learn.microsoft.com
  2. FormatApplicationUserModelId function (appmodel.h) - Win32 apps | Microsoft Learn learn.microsoft.com