Can a packaged with external location WinUI 2 (C++/WinRT) application receive WNS Raw Notifications via a background task?

Rohan Pande 515 Reputation points
2026-07-24T08:25:16.0833333+00:00

Hi,

I'm trying to implement background processing triggered by WNS Raw Notifications, similar to what is described in the Microsoft documentation here - https://learn.microsoft.com/en-us/windows/apps/develop/notifications/push-notifications/raw-notification-overview#background-tasks-triggered-by-raw-notifications

My application has the following characteristics:

  • Win32 desktop application
  • WinUI 2 (XAML hosted)
  • C++/WinRT
  • Package with external location
  • Does not use the Windows App SDK
  • Not a UWP application

The Microsoft documentation explains how a UWP application can register a PushNotificationTrigger background task so that a Raw Notification can wake the app even when it isn't running.

However, I haven't found any documentation describing whether this is supported for package with external location application using WinUI 2.

My goal is:

  1. Register with WNS and obtain a notification channel.
  2. Receive a WNS Raw Notification while the application is not running.
  3. Execute some background code without launching the application's UI.

Questions?

  1. Is PushNotificationTrigger supported for a package with external location Win32 application?
  2. If so, can someone point me to the required registration steps or a sample would also help?
Windows development | Windows API - Win32
0 comments No comments

Answer accepted by question author
Taki Ly (WICLOUD CORPORATION) 4,615 Reputation points Microsoft External Staff Moderator
2026-07-24T10:32:21.5333333+00:00

Hello @Rohan Pande ,

Thank you for providing such a clear description of your scenario.

PushNotificationTrigger is supported for packaged with external location Win32 applications, but the implementation differs significantly from the standard UWP approach. Because your application is a Win32 desktop app, it typically cannot use the UWP in-process background task model natively in the same way. Instead, Windows expects you to implement an Out-of-Process COM Server to receive the raw notification when the application is not already running.

To achieve this, you might consider the following approach:

1. Implement the Background Task via C++/WinRT COM

Your application needs to implement the IBackgroundTask interface and register it as an out-of-process COM server. When a raw notification arrives while the app is closed, Windows will launch your executable with a -BackgroundTask command-line argument.

You can intercept this argument in your WinMain to instantiate the COM class factory instead of initializing your XAML UI, allowing you to run pure background code.

Example structure:

#include <windows.h>
#include <unknwn.h> // Must be strictly included before winrt headers
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.ApplicationModel.Background.h>
#include <winrt/Windows.Networking.PushNotifications.h>
using namespace winrt::Windows::ApplicationModel::Background;
struct PushTask : winrt::implements<PushTask, IBackgroundTask>
{
    void Run(IBackgroundTaskInstance const& taskInstance)
    {
        // Execute your background code here without UI
    }
};
class PushTaskFactory : public winrt::implements<PushTaskFactory, winrt::non_agile, IClassFactory>
{
public:
    HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept override
    {
        *result = nullptr;
        if (outer) return CLASS_E_NOAGGREGATION;
        try {
            *result = winrt::detach_abi(winrt::make<PushTask>());
            return S_OK;
        } catch (...) { return winrt::to_hresult(); }
    }
    HRESULT __stdcall LockServer(BOOL) noexcept override { return S_OK; }
};

2. Update your AppxManifest.xml

For the OS to map the windows.backgroundTasks extension to your COM Server, you would define a CLSID and map it to your executable.

For packaged with external location apps, deploying via MSBuild may occasionally throw validation errors regarding inProcessServer requirements depending on the toolset version. You can manually register the manifest using PowerShell (Add-AppxPackage -Register), bridging it to the COM Server:

<Extensions>
  <Extension Category="windows.backgroundTasks" EntryPoint="YOUR-GUID-HERE">
    <BackgroundTasks>
      <Task Type="pushNotification" />
    </BackgroundTasks>
  </Extension>
  <com:Extension Category="windows.comServer">
    <com:ComServer>
      <com:ExeServer Executable="YourApp.exe" DisplayName="Push Notification server">
        <com:Class Id="YOUR-GUID-HERE" DisplayName="Push Task" />
      </com:ExeServer>
    </com:ComServer>
  </com:Extension>
  <!-- Depending on your OS build validation, an empty dummy inProcessServer declaration might be required by the parser to bypass Win32 schema validations -->
  <Extension Category="windows.activatableClass.inProcessServer" xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10">
      <InProcessServer>
          <Path>dummy.dll</Path>
          <ActivatableClass ActivatableClassId="YOUR-GUID-HERE" ThreadingModel="both" />
      </InProcessServer>
  </Extension>
</Extensions>

3. Register the task at runtime

Even with the manifest declared, the OS requires the runtime registration to route the push payloads. When the app is launched interactively (with UI), you would request access and register the trigger:

auto accessStatus = BackgroundExecutionManager::RequestAccessAsync().get();
PushNotificationTrigger pushTrigger;
BackgroundTaskBuilder builder;
builder.Name(L"PushBackgroundTask");
builder.SetTrigger(pushTrigger);
// The task entry point must strictly match the CLSID in your manifest
builder.TaskEntryPoint(L"YOUR-GUID-HERE"); 
BackgroundTaskRegistration registration = builder.Register();

For further reading on background tasks and identity mapping, you can refer to:

I hope this points you in the right direction. Please let me know if you have any questions or run into unexpected validation issues during your deployment testing issues. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

Thank you.

Was this answer helpful?

1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.