UWP app with Systray extension

A common piece of feedback from folks exploring the move from Win32/NET to UWP is about the lack of Systray (aka notification area) support in UWP. It is true that UWP code can’t run in the Systray, however a UWP package can contain a Win32/NET component that can put itself into the Systray. The UWP package will still be universal (run on Surface Hub, Windows Phone, etc.), and light up the PC-specific Systray functionality on the desktop edition only. In this post I will explain how this can be accomplished on Windows 10.


See source code on GitHub and install the demo app from the Windows Store:
Get it on Windows 10

First step is adding a WinForms project to your UWP solution. It can be done in C++/Win32 as well, but personally I find WinForms to be the most convenient framework for legacy Systray component development. Next add a class file (in my case called ‘SystrayApplicationContext.cs’) to implement all your systray functionality.


To connect the UWP app and the WinForms systray component, we will be using the following two UWP platform features on Windows 10: FullTrustProcessLauncher and AppService. For the former we need to add a reference to the Windows 10 Desktop Extensions SDK:


Now we can declare the “windows.fullTrustProcess” and “windows.AppService” extensions in the manifest for our UWP app package. Note also the two capability declarations. The first one is needed for launching the WinForms code from the UWP, the second one we will need in order to intercept the CloseRequested event (when the user hits the “X” on the window). The latter is somewhat unrelated to the topic of this post, but it’s an implementation choice I made for the sample app – and might be useful for your similar scenarios. Note that this API is available in the Creators Update in preview state.


With the project structure and manifest declarations in place, we can start implementing the desired functionality. First, we want to intercept the user’s close gesture by subscribing to the CloseRequested event:

SystemNavigationManagerPreview mgr =
mgr.CloseRequested += SystemNavigationManager_CloseRequested;

When the event got triggered we let the user decide if/how they want to close the app. If they chose “Close to Systray” we will launch our WinForms component that will continue to run our code in the notification area. Note that I am only making this call on systems that support the FullTrustAppContract. This way my app will still be universal and work correctly on all editions of Windows 10, such as Surface Hub or Windows Phone:

case CloseAction.Systray:
 if (ApiInformation.IsApiContractPresent(
  "Windows.ApplicationModel.FullTrustAppContract", 1, 0))
 await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();

Now switching over to the WinForms component. All the relevant code lives in SystrayApplicationContext.cs. I am implementing basic functionality here in the context menu to demonstrate a couple of common concepts:

  1. Open UWP” – restores the UWP app back to the foreground
  2. Send message to UWP” – sends a message via AppService, the UWP will display it as toast (if in background) or dialog (if in foreground)
  3. Open legacy companion” – displays a WinForms UI that is implemented in the same component, included in our UWP package
  4. Exit” – exits both the WinForms and UWP processes

Here is how we hook up the menu handlers. Explore the full source code on GitHub for details on each of the menu actions.

public SystrayApplicationContext()
 MenuItem openMenuItem =
 new MenuItem("Open UWP", new EventHandler(OpenApp));
 MenuItem sendMenuItem =
 new MenuItem("Send message to UWP", new EventHandler(SendToUWP));
 MenuItem legacyMenuItem =
 new MenuItem("Open legacy companion", new EventHandler(OpenLegacy));
 MenuItem exitMenuItem = new MenuItem("Exit", new EventHandler(Exit));
 openMenuItem.DefaultItem = true;

 notifyIcon = new NotifyIcon();
 notifyIcon.DoubleClick += new EventHandler(OpenApp);
 notifyIcon.Icon = SystrayComponent.Properties.Resources.Icon1;
 notifyIcon.ContextMenu = new ContextMenu(new MenuItem[]
   { openMenuItem, sendMenuItem, legacyMenuItem, exitMenuItem });
 notifyIcon.Visible = true;

Two of the actions I want to highlight real quick, as they are using UWP features, called from the WinForms component, which may be a bit of a new concept for some readers. To get access to those APIs (AppListEntry and AppServiceConnection) I just need to add a reference to the Windows.winmd in my WinForms project. Then I can make these calls:

private async void OpenApp(object sender, EventArgs e)
 IEnumerable<AppListEntry> appListEntries = await Package.Current.GetAppListEntriesAsync();
 await appListEntries.First().LaunchAsync();

private async Task SendToUWP(ValueSet message)
 if (connection == null)
  connection = new AppServiceConnection();
  connection.PackageFamilyName = Package.Current.Id.FamilyName;
  connection.AppServiceName = "SystrayExtensionService";
  connection.ServiceClosed += Connection_ServiceClosed;
  AppServiceConnectionStatus connectionStatus = await connection.OpenAsync();
 await connection.SendMessageAsync(message);

Hope this information was useful for some of you and will help you when you make the jump from Win32/NET to UWP on Windows 10. Please leave your questions and comments here and I will respond as soon as I can.


76 thoughts on “UWP app with Systray extension

  1. The Systray can’t support background media player of the UWP project.
    When I closed the app, the background task still be received the cancel event.

    Because I want to implement the feature:
    When app be close, the background media player can keep play music in the Systray.

    Is it possible? thank you.


  2. Thank you for this great article.
    I would like to ask a question.
    If I update my existing UWP app that is published in store to use capabilities mentioned here, should I expect anything unusual? I mean, I’ve seen that projects that are converted through the bridge are publishing with a special onboarding process, will it also be the case for my app?


    1. Yes, when you submit your update that adds the ‘runFullTrust’ capability the submission will go through a special onboarding review. Let me know if you run into any problems with that.


  3. Hi and thank you for a great article.
    I would like to ask a question.
    I have a UWP app published in store, and I would like to know if there would be any obstacles while publishing an update if I update my app to use the capability mentioned here.


  4. did something break with fall creators update? I get the error c:\program files\windowsapps\….\Systraycomponent.exe -> The data area passed to a system call is too small. This was installed from the store. I haven’t tried from the repository yet.


      1. Well timing is everything. We’ll have to wait for the CU for SQL to come out to fix this as the article says, we’re using filestreams in the database. Good to know though for future.


  5. Dear Stefanwick,

    As per our current analysis, systray app is just acting like a Dock in the system tray. It is stopping its activity immediately after minimized to systray.

    We are having the following requirement:

    Once the app minimized to systray, It should be running in background and keep on sending SendIOControlAsync() [Async IOCTL from UWP] request from background to a custom kernel mode driver [for a virtual device].

    Once we got response from driver it should show notification to user.

    Note: Background task worker thread can be invoked only by the response from driver. We don’t have any system event to invoke it. Also the driver will respond back to the Async IOCTL only after 1 hr/2 hr.(It means we could not define a specific response time period)

    Will that be supported in UWP systray app?

    Your suggestions are greatly appreciated.



    1. I think your question is really unrelated to the systray. You can keep the UWP running when minimized – no need for systray to do this. Take a look at this: https://docs.microsoft.com/en-us/windows/uwp/launch-resume/run-in-the-background-indefinetly

      You may or may not have a systray presence – that’s really your design choice.

      Regarding this sample: yes, the UWP process by default stops executing when minimized, but the systray component keeps running, so you could also just make those periodic calls from that component. This has the added advantage that you have access to the full Windows API from that component, whereas the UWP process is limited to the UWP API surface.


  6. I have a requirement to host a WCF service to receive responses from a service. As UWP app doesn’t have wcf hosting capabilities, I chose this system tray component where I will host my service so that I get responses and communicate to UWP app via app service and show toasts.

    But I couldn’t figure out what’s happening, the systray component terminates immediately after the launch. To be clear on my systray integration with uwp I already tested it and is working and then extended it with WCF hosting.

    Is there any issue in my concept or this scenario isn’t acceptable with UWP?
    Kindly help.


    1. Hi Siddhardha,

      I can’t think of any reason why this wouldn’t work. We would need more details to analyze why it’s not working. Have you run this under a debugger yet? You might want to put this out on Stackoverflow and we’ll get you an answer there.



  7. Hi Stefanwick

    Wonderful work! But I ran into an issue. My UWP app is in JavaScript and I used your C# code for Systray Extention. I ran into this weird error of “The type or namespace name ‘Windows’ does not exist in the namespace ‘System’ (are you missing an assembly reference?)”. I added the System.Windows.Forms reference too and I tried changing the .NET framework version to 4.5.2 and then the error changed to “The type or namespace name ‘ApplicationModel’ does not exist in the namespace ‘Windows’ (are you missing an assembly reference?)”. Can you please help me with this.



      1. Thanks a ton! It works great except that when I open from the system tray, the app restarts to its home page, even when the app is just minimized and not closed. Is there a way to open the app at its current page if it is in suspended state?



  8. Hey Stefanwick,

    Fantastic tutorial, thanks so much!

    Quick question – I’m trying to initialize Firebase (step-up-labs version) in the SystrayComponent, but it seems to crash. Is there any way to see the error messages being thrown? I’m also using JS for the UWP app and logs from that appear fine.

    Is there anything I’m missing to get the Firebase initialization working? (e.g. internet permissions etc.?) https://github.com/step-up-labs/firebase-authentication-dotnet



  9. Hi Stefanwick

    Did you find a way to give admin rights to the win32 app? I’m asking because I’d like to log to EventViewer and I need admin rights in order to create a source. Also, I’ve tried to use MetroLog for both apps, but I can not find the log files for win32 app, only for UWP one. What would you recommend for logging here?



    1. Hi Adrian:

      there are two answers to your question:

      1. being able to run the win32 process with admin privileges is a new feature that is coming in the 2018 fall update of Windows 10. It should already be working in current insider builds (need to declare the new restricted capability “allowElevation”). Hope I can share a sample for this soon.

      2. Just for the purpose of logging you should not be required to elevate. Not very familiar with Metrolog, but have you raised an issue with them? Note that declaring the new capability for elevation may prevent you from shipping in the Store, so this may not be the preferred route for this problem anyway.



  10. I have tried converting an existing application using Desktop App Convertor by providing input as the .msi file from the installer package folder path of my existing desktop application. I tried installing it and using the application post conversion and it works.. But I have few questions below.

    1. The converted application couldn’t be launched on the OS version which is less than the Base image version took for conversion. Is this expected? So if we want to support old versions should we take the 10.0.14393 as base image and convert?

    2. Post installing the converted app, launched WACK to test the installed app and it fails for “Package sanity test” saying ProcessorArchitecture is x86 in manifest and these 2 dll’s (comctl32.dll & GdiPlus.dll) were of x64 config.
    I didn’t mentioned anywhere as x86 during conversion, no idea how it is taken in manifest. How to resolve this?

    3. The converted application has only .appx created, no .appxupload file generated. For these kind of converted applications case how to reach the Store?


    1. Hi SiD,

      1. just set MinVersion=”10.0.14393.0″ in your appxmanifest file to support that version, assuming your app doesn’t depend on OS features that have been added only in later versions

      2. use -packageArch parameter to specify x64 if you intended to create an x64 package

      3. you can upload .appx files to the store as well. But if you want to go with .appxupload, the best way to create an .appxupload file for your Win32 application would be to use the Visual Studio packaging project for creating the packages.

      Btw, for general questions like these that aren’t directly related to the blog post, I recommend using stackoverflow with tag “DesktopBridge” in the future, to get the best visibility and traction on your requests.



      1. 1. As I used the Convertor I had not prepared any manifest manually. Post Conversion it is generated automatically and it already has min version tag with 14393 version. Still it is not launching on RS1 & RS2.

        2. So do you mean we have to generate multiple packages with same desktop application input to generate separate appx?

        3. As this is converted app using the converted tool, I can’t package it through Visual Studio as I’m not using the source but making use of the builded product i.e. msi file.


  11. 1. Need more details about the app to answer that. I suggest you post a question on stackoverflow with repro and/or logs.

    2. It’s your choice. If you want to distribute multiple architecture then you will need to create multiple appx package – one for each architecture. You can then zip them up and rename to .appxbundle to combine all of them and submit them in one shot to the Store.

    3. It’s possible to use the packaging project also with pre-built binaries, but you don’t have to use VS to create an .appxupload file. You can create it manually, it’s just a zip file that contains the .appxbundle and the .appxsym file. Then again, you need to have an .appxupload as you could also submit either the .appx or the .appxbundle file directly to the Store.


  12. Hi Stefanwick,

    Thanks for the excellent sample for enabling Uwp UI to be rendered in response to systray [ / notification area ] process context menu selections. A couple of related questions . . .

    q1. When I f5 on the SystrayExtension and try to debug through SystrayComponent breakpoints that doesn’t work as it appears vs17 15.8.2 debugger launch process doesn’t successfully hookup debugger to both processes. Is there a trick to making that work? All I’ve been able to make work thus far is launch a debug version of SystrayExtension from outside of vs17 that I then close to leave SystrayComponent process running at which point I attach vs17 debugger to in order to get support for stepping through all but startup code for SystrayComponent.

    q2. If I want startup to immediately got to minimized SystrayComponent process presence, vs uwp UI view, would I just have SystrayExtension | MainPage.xaml.cs | SystrayExtension OnNavigatedTo() event issue a call to version of SystemNavigationManager_CloseRequested() event handler that executes the case CloseAction.Systray: steps?

    q3. Currently the SystrayComponent display what appears to be a SystrayApplicationContext constructor runtime defined Windows.Forms based context menu. Is there a way to have it instead pop a SystrayExtension defined uwp UI above the systray icon when context / right mouse button is clicked similar to what it seems the OneDrive, Sounds and Windows Ink Workspace do?


    1. For Q1: this is currently a gap in the Visual Studio debugging support. It does not automatically attach to both processes as you would expect. The VS team is looking into possible solutions.

      For Q2: You would just call FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync() during start up of the UWP app, e.g. from your MainPage’s OnNavigatedTo event.

      For Q3: A UWP UI is currently not supported there. However, with the new RS5 support for hosting UWP-XAML in Win32 processes you should be able to accomplish such scenarios.

      Liked by 1 person

      1. Thanks for the responses, that helps.

        Any reason why with this uwp desktop bridge scenario a person shouldn’t be using a “windows application packaging project” to produce the store publishing upload similar to what you made use of in GlobalHotkey uwp desktop bridge sample vs the package output of the SystrayExension uwp app project?


      2. Actually, it’s highly recommended to use the Packaging project also for this type of scenario. The only reason I was not using it here is because I created this sample a long time ago before the Packaging project was able to support the scenario (and then I never found the time to update it later).

        Liked by 1 person

      3. In the derivation of your sample i’m working on i created a SystrayComponent | SystrayApplicationContext.cs user input event handler that opens a registry key for read and write purposes [ using (RegistryKey key = Registry.CurrentUser.OpenSubKey(“Control Panel\\Mouse”, true)) ] that is successfully able to read the SwapMouseButtons value but fails to write it.

        The exact same code running in a .net framework console app is able to successfully write to that key/value without requiring any “run as administrator privileges”.

        Is there some setting i’m overlooking that is necessary to allow the .net framework / winforms based SystrayComponent to be able to write to hkcu paths?


      4. Thanks for response. If one where to make their systray [ / notification area ] application using only .net framework windows app project, e.g. the systraycomponent project only, would that change this restriction?


      5. Thanks for clarification that helps. Sounds like one would have to resort to a wix msi installed set of bits if it was critical to app experience that you have a way to get around the registry hkcu write security issue.


  13. Any insight how in the Uwp Page OnNavigatedTo() handler I could determine if page is being opened as a result of desktop extensions launched systray component’s “Open UWP” menu item?

    I ask because in the Uwp Page OnNavigatedTo() I have code that automatically uses desktop extension to launch systray component and then close, versus having to do that step manually, and then when user selects “Open UWP” and it gets reopened I have to find a way to not carry out those steps in that case.


    1. . . . I thought I could maybe use the connection.SendMessageAsync(message) approach to reopening it but when I look at MainPage.xaml.cs OnNavigatedTo parameter NavigationEventArgs e I don’t see a way to access sent message and that wouldn’t help anyway because that requires a person to manually click the notification popoup in order to relaunch the UWP Page view.


      1. . . . using uwp app ApplicationData.Current.LocalSettings.Values[“systrayComponentLaunched”] = true; to track it having launched systray component using desktop extensions and then using ApplicationData.Current.LocalSettings.Values.Remove(“systrayComponentLaunched”); in systray component exit to capture it having been closed.


    2. In the sample I am using AppListEntry.LaunchAsync() to launch the UWP, which doesn’t provide any context/parameters. What you could do instead is do a protocol launch, which will allow you to pass in arbitrary parameters. This way you can detect that the launch came from the systray component.


  14. Thanks for suggestion I am exploring package manifest | declarations | add | Protocol coupled with use of Windows.System.Launcher.LaunchUriAsync.

    I’m also looking at your GlobalHotKey sample which makes use of desktop extensions and am finding that its MainPage.xaml.cs | OnNavigatedTo is able to call System.Diagnostics.Process.GetCurrentProcess(); which it stores in a LocalSetting for access later by desktop extensions launched win32 app process.

    I tried introducing this same call into my derivative of your uwp SystrayExtension + win32 SystrayComponent sample provided here and it doesn’t accept it, “The type or namespace name ‘Process’ does not exist in the namespace ‘System.Diagnostics’ (are you missing an assembly reference?)”

    Looking at uwp app references in both samples, this one and GlobalHotKey one, i’m seeing same Analyzers, Microsoft.NETCore.UniversalWIndowsPlatform, “Universal Windows” and “Windows Desktop Extensions for the UWP” entries.

    Any insights as to what i’m overlooking that is necessary to enable use of System.Diagnostics.Process.GetCurrentProcess() call?


    1. In order to use System.Diagnostics.Process.* make sure both your Min and Target versions are set to 16299 (or higher) in the UWP project – and make sure you reference a current Microsoft.NETCore.UniversalWIndowsPlatform package.


      1. Thanks for details. The min version in systrayextension was set to creators update 15063 which I changed to fall creators update 16299 and the Microsoft.NETCore.UniversalWindowsPlatform package was set in SystrayExtension.csproj to 5.2.3 which I manually updated to 6.1.9 version used in new | project | c# | windows universal | blank app. I did that manually as it wasn’t clear how to remove and re-add that package reference to pickup the latest version reference.


    1. . . . tried “Window.Current.Close();” and it generates a “System.Runtime.InteropServices.COMException: ‘A method was called at an unexpected time. Closing main window is not allowed.'”


  15. Thanks that helped. With that matter addressed I was all excited to have my uwp store app, that made use of the desktop bridge/extensions functionality you covered in this sample and your followup global hotkey one [ https://stefanwick.com/2018/05/15/global-hotkey-registration-in-uwp/ ], published in the store. I went through the submission process and they responded with a no where the certification report just says the issue is “Your account has not been approved for the Centennial program.”. There was no guidance in that report, or at https://developer.microsoft.com/en-us/windows/bridges/desktop that i could readily see, on next steps to get my developer microsoft account approved for the Centennial program, which appears to be marketing name for release of desktop bridge/extensions services to help get more owners of windows desktop apps to slowly migrate and publish them as store apps. Any pointers you can provide as I posted question about this to desktop bridge support forum [ https://social.msdn.microsoft.com/Forums/windowsapps/en-US/88bdb12e-a276-4054-bc89-70e232dd9e23/getting-developer-microsoft-account-msa-added-to-centennial-program-aka-desktop-bridge-?forum=wpdevelop ] and haven’t gotten any leads to this matter from that as of yet?


  16. Hi Stefan,

    I’ve actually tried to implement the systray component into my existing solution but ran into a problem concerning the async OpenApp method.

    This is what it tells me : http://oi65.tinypic.com/jinhuc.jpg

    Any help on that? I’ve checked the windows.winmd version, the .Net Framework version and the output type of the Systray component project I created, which is all the same as yours.



      1. Thanks!

        I’ve found it with NuGet Package Manager.

        However, I still need to sort out this error by myself :

        Could not install package ‘System.Runtime.WindowsRuntime 4.3.0’. You are trying to install this package into a project that targets ‘.NETFramework,Version=v4.6.1’, but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

        Will update for anyone else with the same problem if I find the solution


      2. No need to install a Nuget package. You can just add an assembly reference to %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll


  17. Thanks for the solution. Would i be possible to hide the icon from Task bar and only show it in Task tray when minimized?


  18. I’m trying to include a reference to Newtonsoft.JSON in the systray component. I can add the reference but when I try to use it in code, I get an exception:

    Type: System.IO.FileNotFoundException
    Message: Could not load file or assembly ‘Newtonsoft.Json, Version=, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed’ or one of its dependencies. The system cannot find the file specified.

    I’ve tried referencing it through Nuget and by directly referencing the DLL.

    I’ve tried to reference a different .NET Standard library and had the same problem.

    Any suggestions on how to get this reference to work?


  19. Hello,
    My question may be a little bit “stupid” … But where do we find the manifest ? I am at the step where we do have to declare the “windows.fullTrustProcess” and “windows.AppService” extensions in the manifest for our UWP app package.

    But in my UWP folder there is no file “app.manifest”. Where can I find / create it ?

    Thanks for your support


    1. In VS the file you want to edit is called Package.appxmanifest. Based on that file the VS build process then creates AppxManifest.xml, which is the manifest that ends app in your app package.


      1. Thanks for your quick reply.

        I still have an issue with that manifest. The and both are underlined in red and nothing works, VS says that they are not defined … (Btw I’ve added the Windows Desktop for Extension UWP) and I’m under OS 1809.

        Thanks for your support


  20. I updated my store app, based on use of the desktop bridge functionality outlined in this post, from using the 17134 windows.winmd to the new 17763 windows.winmd installed by current vs19 environment

    $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.17134.0\Windows.winmd
    $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd

    Now i’m finding that the “Windows App Certification Kit 10.0.17763.13” is failing on the “Package Sanity Test” “Blocked executables” test saying that “File Win32\SystrayComponent.exe contains a reference to a “Launch Process” related API System.Diagnostics.Process.Start”.

    Does this imply that store app packages are no longer allowed to use this functionality and if so how does one package, publish and share an update to an existing store application that is doing this?


    1. . . . and below the Error Found: details noted about there is a How to fix: entry that says “How to fix: Identify which of the flagged entries represent a call to launch an executable file that is not part of your app and remove those calls. If the flagged files are part of your application, you may ignore the warning.” suggesting i can ignore this.


      1. Yes that test is listed in the “Results for optional tests” section of the “Windows App Certification Kit 10.0.17763.13” output that was kicked off by Package | Store | Create App Packages process.

        I’m also noticing that with vs19 17763 sdk in place the “Windows App Certification Kit 10.0.17763.13” output non-optional tests section is now creating an “App manifest resources tests” | “App resources” subtest failure i wasn’t seeing before stating “Error Found: The app resources validation test detected the following errors: The test was blocked from execution. Please try re-running the validation. If the test execution remains blocked then please contact support.”

        Not a lot of insight in the output or reference link it points to for more help [ App Package Resource Validation -> https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/windows-app-certification-kit-tests#app-manifest-resources-test ] that outlines why this is now surfacing and wasn’t with prior 17134 sdk in place. I guess i can just try and submit the Package | AppPackages | Package_1.1.#.0_x86_bundle.appxupload output file to the store in spite of this non-optional test error and see what happens.


      2. Sorry, can’t help with that. I no longer work on the Windows team. If you are seeing new issues in newer versions of the SDKs or tools, please log a bug and/or reach via official channels. I am unable to provide support on this.

        Liked by 1 person

      3. Yes i understand and appreciate you taking the time to provide your thoughts on this given you long since have moved on to other activities.


  21. Is there a way to start a UWP app in the systray? Opposed to having to press close and then send it to the systray, can you just automatically have it start (and live) in the systray?


    1. Yes and no. You can add the systray entry right away when the app first launches. No need to do it on close. However, after installing the UWP app, the user needs to launch the app at least once in order to get the systray entry, in other words: it can’t be done at install time.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s