Calling Windows 10 APIs From Your WPF Application

Did you know that you can call Windows 10 WinRT APIs from your WPF and WinForms apps? In this blog post I’ll show you how to display toast messages from a WPF application by using the Windows 10 ToastNotificationManager.

In the previous blog post you learned that you can host UWP Controls in WPF, WinForms, and Win32 with a technology called XAML Islands.

But sometimes you don’t want to include a UWP Control in your WPF app. Instead, you want to call a Windows 10 API. Or maybe you want to do both: Include a UWP control and call a Windows 10 API. In any case, you need to reference the Windows 10 WinRT APIs in your WPF project. Let’s see how to do this.

Reference the Windows 10 WinRT APIs in your WPF project

If you’ve tried already in the past to use Windows 10 WinRT APIs in WPF, you might have come across documentation that said that you have to reference several files …

  • … from .NET Framework – like System.Runtime.WindowsRuntime.dll
  • and from the corresponding Windows SDK, like Windows.Foundation.UniversalApiContract.winmd

This is not necessary anymore. Microsoft made this whole process much simpler.

All you need to do to use Windows 10 WinRT APIs in your WPF project is to install the NuGet package Microsoft.Windows.SDK.Contracts.

That package is the the so-called Windows 10 WinRT API Pack . Let me quote the package description:

The Windows 10 WinRT API Pack enables you to add the latest Windows Runtime APIs support to your .NET Framework 4.5+ and .NET Core 3.0+ libraries and apps. This package includes all the supported Windows Runtime APIs up to Windows 10 version 1903

Wow, amazing. Just adding a single NuGet package and it works. Let’s try it.

Add the NuGet package

Let’s create a brand new WPF application and let’s install the NuGet package Microsoft.Windows.SDK.Contracts. It’s still in preview, so ensure to check the “Include prerelease” option like below:

When you look at the dependencies of the Microsoft.Windows.SDK.Contracts package, you can see that it brings in the other stuff that you had to add manually before this package existed, like the System.Runtime.WindowsRuntime.dll that I mentioned above:

Switch from packages.config to PackageReference

When you install the Microsoft.Windows.SDK.Contracts NuGet package in a .NET Core WPF app, you’re fine. But in a .NET Framework WPF app, you have to switch the NuGet package management format from packages.config to PackageReference, else it won’t work. The description of the Microsoft.Windows.SDK.Contracts package contains also this statement:

Requires default package management format set to PackageReference, and NuGet 4.0 or higher.

If you have a .NET Framework WPF app that still uses packages.config, just right-click on “References” in the Solution Explorer. In the context menu you find a menu item to“Migrate packages.config to PackageReference”, as you can see in the screenshot below.

After you clicked that menu item, the packages.config file will be deleted and the references to the NuGet packages are stored in the .csproj file. Great, now installing the NuGet package Microsoft.Windows.SDK.Contracts works fine, and you should see that package including its dependencies in the references like below:

Now, no matter if you’re using .NET Core 3 or .NET Framework, you’re ready to display a toast message from your WPF app. Let’s write the code.

Display a Toast Message

Let’s add a simple Button in the MainWindow.xaml file:

<Button Content="Show Toast"
        Padding="10"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Click="ButtonShowToast_Click"/>

In the codebehind file (MainWindow.xaml.cs), let’s add this ButtonShowToast_Click event handler:

private void ButtonShowToast_Click(object sender, RoutedEventArgs e)
{
    string title = "The current time is";
    string timeString = $"{DateTime.Now:HH:mm:ss}";
    string thomasImage = "https://www.thomasclaudiushuber.com/thomas.jpg";

    string toastXmlString =
    $@"<toast><visual>
            <binding template='ToastGeneric'>
            <text>{title}</text>
            <text>{timeString}</text>
            <image src='{thomasImage}'/>
            </binding>
        </visual></toast>";

    var xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(toastXmlString);

    var toastNotification = new ToastNotification(xmlDoc);

    var toastNotifier = ToastNotificationManager.CreateToastNotifier();
    toastNotifier.Show(toastNotification);
}

As you can see in the code snippet above, the ButtonShowToast_Click event handler initializes a toastXmlString variable with a valid toast template. Then it loads that string into an XmlDocument (the WinRT one from the namespace Windows.Data.Xml.Dom). Next a ToastNotification object is created with that XmlDocument.

Then a ToastNotifier instance is created by calling the static CreateToastNotifier method of the ToastNotificationManager class. Finally, the Show method is called on that ToastNotifier instance to show the toast notification.

You can just copy paste that code snippet into your app. When you place the cursor on the ToastNotificationManager class, you can press “CTRL+.” and Visual Studio will suggest you to add a using directive for the WinRT namespace Windows.UI.Notifications, as you can see below:

For the XmlDocument class, you need to add a using directive for Windows.Data.Xml.Dom (and not for the .NET variant that lives in System.Xml). The using directives of the MainWindow.xaml.cs file look like below. As you can see, a nice mixture between .NET and WinRT namespaces:

using System;
using System.Windows;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;

Now let’s run the application and let’s push the “Show Toast”-Button in the MainWindow.

Let’s click this nice Button.

Oh no, we get an Exception at the line where the CreateToastNotifier method is called. It says “Element not found”. What does this mean?

The problem here is that your WPF application doesn’t have a package identity. A UWP app has a package identity, and it is installed in Windows 10 with that identity. But a WPF app doesn’t have such an identity, so let’s create one.

Create an Identity for Your WPF App

You can easily create an identity for your WPF app by packaging it as MSIX. To do this, just add a Windows Application Packaging Project to your solution. In the previous blog post we used the Windows Application Packaging Project already to target a specific windows version with WPF. This time we need that Packaging Project to get an identity, and in addition, that Packaging Project let’s us target a specific windows version. So let’s add it. Let’s right-click the solution and let’s add a new Windows Application Packaging Project.

My WPF project is called “WpfCallingWin10Api.Framework”. Let’s call the packaging project “WpfCallingWin10Api.Framework.App. The creation shows the dialog below, where I select 18362 as a minimum version:

After that packaging project was added to the solution, you have to right-click the “Applications” node in Solution Explorer to reference the WPF project. Finally, set the packaging project as a startup project. The final result should look like this:

Now with the Packaging Project set as a start up project, let’s try the app again, as we have now an identity.

Let’s Toast It!

Let’s run the application and let’s click the “Show Toast”-Button.

*drumroll*

And voilà! In the bottom right corner of my screen, above the icon tray, appears a nice toast that displays the current time like we’ve specified it with the toast template, including the thomas.jpg that we’ve also specified in that toast template.

The toast is shown above the icon tray in the bottom right corner of my screen.

Fantastic, it just works!

And all that was necessary were these 2 steps:

Go and Grab the Code!

I have created this sample for you with .NET Framework and .NET Core. Grab the .NET Framework and .NET Core solutions from this Git repository to try it on your own, and don’t forget to set the packaging project as a startup project:

https://github.com/thomasclaudiushuber/Wpf-Calling-Win10-WinRT-Toast-Api

Can we talk again about XAML Islands?

Sure. What’s the question?

Hey Thomas, at the beginning of this blog post you wrote this:
“… sometimes you don’t want to include a UWP Control in your WPF app. Instead, you want to call a Windows 10 API.  Or maybe you want to do both: Include a UWP control and call a Windows 10 API. In any case, you need to reference the Windows 10 WinRT APIs in your WPF project. Let’s see how to do this. “

But in your previous blog post where you used XAML Islands to display the UWP MapControl in a WPF app, you neither referenced the UWP .winmd file, nor did you install the Microsoft.Windows.SDK.Contracts package. But in this blog post you’re saying “In any case, you need to reference the Windows 10 WinRT APIs in your WPF project.”

In your previous blog post you didn’t add a reference, why did it work there?

Ok, let’s answer this.

In the previous blog post we installed the NuGet package Microsoft.Toolkit.Wpf.UI.Controls. That package contains wrapper controls for WPF that make the usage of UWP controls like MapControl and InkCanvas straight forward. Or in other words: That package makes the usage of XAML Islands straight forward.

We installed the preview4 version of that NuGet package. And now go and click here on this NuGet link to look at the Dependencies of the preview4 version of that package, the latest available version.

Instead of clicking on the link above, you can also manage NuGet packages in Visual Studio, search for that preview version of the Microsoft.Toolkit.Wpf.UI.Controls package, click on it and look at its dependencies. The dependencies of that Microsoft.Toolkit.Wpf.UI.Controls package look like below. Do you notice something?

Exactly, the package Microsoft.Toolkit.Wpf.UI.Controls has a dependency on Microsoft.Windows.SDK.Contracts.

That means in other words: If you’re using that XAML Islands NuGet package, you automatically get access to the Windows 10 WinRT APIs, as Microsoft.Windows.SDK.Contracts is added too, as it is a dependency.

Isn’t this awesome? I love it!

Happy coding,
Thomas

Share this post

Comments (32)

  • Dew Drop – April 29, 2019 (#2947) | Morning Dew Reply

    […] Calling Windows 10 APIs From Your WPF Application (Thomas Claudius Huber) […]

    April 29, 2019 at 12:43 pm
  • Robert Mühsig Reply

    Is the MSIX still needed for the deployment? I read somewhere that with the most recent Win10 Version even non UWP/MSIX apps should be able to use the Win10 APIs, e.g. a „classic“ WPF app.

    May 5, 2019 at 6:10 pm
  • Fabio Corvino Reply

    Sorry, but there is something that is confusing me and the overall process is not working.
    I’m using .NET Framework 4.7.2 and Windows 1803.
    So, the statement: “The Windows 10 WinRT API Pack enables you to add the latest Windows Runtime APIs support to your .NET Framework 4.5+ and .NET Core 3.0+ libraries and apps. This package includes all the supported Windows Runtime APIs up to Windows 10 version 1903”, for me (Italian) it means that it supports also previous versions.
    Unfortunately if I configure the Packaging Project to run for 18362 min 17134, I get the error: “Your application has a dependency on ‘WpfAppCallingWin10API’, which has a TargetPlatformMinVersion of ‘10.0.18362.0’. Your application’s TargetPlatformMinVersion is ‘10.0.17134.0’. Change ‘WpfAppCallingWin10API’s TargetPlaformMinVersion to be less than or equal to ‘10.0.17134.0’.”
    Whereas if I configure the Packaging Project to run for 18362 min 18362, it compiles but, when I start it, I receive the error: “DEP3321: To deploy this application, your deployment target should be running Windows Universal Runtime version 10.0.18362.0 or higher. You currently are running version 10.0.17134.829. Please update your OS, or change your deployment target to a device with the appropriate version.”
    Am I missing something?

    June 20, 2019 at 9:55 am
  • Harish Kaushal Reply

    A BIG THANK YOU Thomas for this article. I was struggling to solve element issue in my WPF app. But now i have another issue and i want to ask if its possible or not.

    I am actually new to .NET coding and your Pluralsight courses has helped me a lot. Thank you :)

    Issue :-

    I have WPF app and using above method i have enabled toast notifications for my app. But i want my app to have “Run As different User” option because of some business requirement. But now start up project is UWP app so now i don’t have that option anymore.

    So is there any way i can have “Run As different user” option for my UWP app?

    Appreciate your response.

    July 3, 2019 at 11:14 am
    • Thomas Claudius Huber Reply

      Hi Harish, great question. I don’t have an answer for this yet. I need to try it. But maybe you want to use an application.manifest in a normal Win32 WPF app instead of using the packaging project that makes it a UWP app.

      September 12, 2019 at 10:07 am
  • Taras Reply

    Hi Thomas,
    What options do I have if I want to develop my app for Windows 7+, but also want to use Win10 APIs when the app is running in Win10?
    Is recompiling an app for Win7 without referencing Win10 DLLs a must?

    July 4, 2019 at 2:28 pm
    • Thomas Claudius Huber Reply

      Hi Taras,

      great question. I think so it is a must, as you need to change the application manifest

      September 12, 2019 at 10:05 am
  • Callon Reply

    Great post. Have you tried using the Win10 share Contract in a WPF app? Following your guidelines above results in the same error even through I wrapped it in a Windows Package Installer.

    August 5, 2019 at 5:50 pm
    • Callon Reply

      The error I get is…

      System.Exception: ‘Element not found.

      This method cannot be called while the app is in the background’

      August 5, 2019 at 5:52 pm
    • Thomas Claudius Huber Reply

      Hi Callon, I haven’t tried to use that contract yet.

      September 12, 2019 at 10:04 am
  • Leszek Reply

    Windows 10 version 1903
    Does it always needs to be shown with the latest windows version? Writing application for business means that the business is NOT on the latest version of Windows.

    Can a packaged app be still deployed using ClickOnce?

    How to use loggers, like log4net, etc. that writes to a file outside UWP Storage?

    How to use old, non NET STandard 2.0 technologies, like Linq2SQL within UWP UI Project?
    using AppService and Net Framework project as proxy?

    Best regards

    August 8, 2019 at 9:39 am
    • Thomas Claudius Huber Reply

      Hi Leszek,

      great questions. I don’t have answers to all these questions. But with UWP, you get a similar deployment model like ClickOnce that allows you to use a URI for the package. I think MSIX is the future for deployment and packaging.

      Linq2SQL is really old. I think you should move that code to Entity Framework Core

      September 12, 2019 at 10:10 am
  • Max Reply

    Hi Thomas,
    thanks for the great article! I didn’t know that there is a NuGet package available, this helps alot.

    I have a little addition: You only need the workaround with the identity project if you are using “”. There are some templates which are working without the workaround.

    You can find the templates here:
    https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh761494(v=win.10)?redirectedfrom=MSDN

    Best regards

    October 29, 2019 at 12:08 pm
  • JSGURU Reply

    Hi, Thomas
    It is a fantastic article. I could implement toast notification on my project from your article.
    But I want to try to make a standalone exe of your project(DotNetFramework).
    I dont know how to do. I will appreciate if you help me.

    December 7, 2019 at 9:24 pm
  • jstopguru Reply

    Hi, Thomas

    Your post is a fantastic article. I could implement toast notification on my WPF .Net Framework project from your post.
    But I could not build a standalone exe file of my project.
    Could you let me know how to make it with your https://github.com/thomasclaudiushuber/Wpf-Calling-Win10-WinRT-Toast-Api/tree/master/DotNetFramework?

    December 8, 2019 at 1:48 pm
  • JSGURU Reply

    Hi, Thomas
    I did not hear from you.

    December 9, 2019 at 6:17 pm
  • Igor Reply

    Hi Thomas, great article. I was able to make it work with the ToastNotificationManager, but when I try to use InputPane.GetForCurrentView() I get the same error “System.Exception: ‘Element not found. (Exception from HRESULT: 0x80070490)'”

    Do you have any suggestions how to solve this issue?

    February 25, 2020 at 3:41 pm
    • Thomas Claudius Huber Reply

      Hi Igor,

      that’s a good question. I think GetForCurrentView is problematic when you use the Control via XAML Islands in WPF/WinForms. There’s a known issue here on GitHub: https://github.com/microsoft/microsoft-ui-xaml/issues/687

      Where and why are you calling it?

      Best,
      Thomas

      February 26, 2020 at 5:27 pm
      • Igor Reply

        Thanks for the reply, Thomas.
        I was trying to subscribe to the touch keyboard’s showing/hiding events, to adjust control’s position, so that they are not covered by the keyboard. I found multiple solutions and none of them seem to work. I.e. they all compile and run, but event handlers are not executed. For now I have to use control’s focus events and a loop to wait for keyboard window to appear, which doesn’t look like an optimal solution.

        Regards,
        -Igor

        February 26, 2020 at 6:46 pm
  • Stefan Tucker Reply

    One big downside to using UWP APIs is that APPX packaging requires a code-signing certificate which costs approximately USD $100/year. Not everyone can afford this, especially for publishing free apps. I think Microsoft has a long, uphill battle to get developers to switch to using anything in UWP. As much as I would love to use toast notifications in my app (instead of message boxes), it’s not worth paying $100/year for that.

    April 13, 2020 at 3:33 am
  • Mohammad Shahjahan Mia Reply

    Great tutorials . Thanks. How Can I Toast notification event ? go to my desired form.

    Thanks
    Mohammad Shahjahan Mia

    May 15, 2020 at 5:58 am
  • Didddy Reply

    Works great! Nice How-To!

    November 11, 2020 at 7:35 pm
  • Spanos Nikos Reply

    Hey Thomas, nice article. However, after following your instructions and code I get the following error
    “The target process exited without raising a CoreCLR started event. Ensure that the target process is configured to use .NET Core. This may be expected if the target process did not run on .NET Core.” This error is generated the moment I click the Debug button for x64 CPU in VS 2019.

    Do you have any idea how can I resolve this error? I followed every step of your tutorial. I use WPF application on .NET Core 3.1

    January 6, 2021 at 11:56 am
    • Thomas Claudius Huber Reply

      Hi Spanos, interesting. Doesn’t ring any bells here. Did you try to run it with x86 instead of x64?

      January 20, 2021 at 12:29 pm
  • Donald Cole Reply

    Hey Thomas,

    Im having an issue where trying to use the contracts Nuget package with targeting .net 4.5 in Visual studio 2017, specifically to bring in the Windows.Devices.Enumeration namespace.
    I am using Windows 10 SDK (10.0.17763.0), Microsoft.Windows.SDK.Contracts (v10.0.17763.1000) and Visual Studio 2017 Version 15.9.31.

    All of the references are added just fine, except I am unable to import any using statements from the API using these versions even though from all of the documentation and websites I read that .net 4.5 is supported. Any theory or help would be appreciated, Thanks!

    January 19, 2021 at 10:48 pm
    • Thomas Claudius Huber Reply

      Hey Donald, I’m not sure what went wrong on your machine and with your app. Did you try if VS2019 might do the job?

      January 20, 2021 at 12:27 pm
      • Donald Cole Reply

        Thanks for the quick reply, due to client/company requirements I must use VS 2017 and would *like* to use .net 4.5. But it does work on VS 2019 with .net core 3.1 and VS 2017 with .netstandard 2.0 which is my current working route I am going with. I have not actually tried VS 2019 and targeting .net 4.5 and will give that a shot just to see if it works.

        January 20, 2021 at 4:24 pm
  • aboubakr Reply

    i have created the same project that u did but every time i click on the notification it relaunch the notification app so i would have two running at the same time, iwant to disable that how can

    October 27, 2021 at 4:03 pm
  • Sam Hobbs Reply

    When I install the NuGet package Microsoft.Windows.SDK.Contracts the compiler tells me to remove it. Apparently it has become even easier.

    November 29, 2023 at 7:58 am

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.