Extend your desktop application with modern UWP components

Some Windows 10 experiences (For example: a touch-enabled UI page) must run inside of a modern app container . If you want to add these experiences, extend your desktop application with UWP projects and Windows Runtime Components.

In many cases you can call UWP APIs directly from your desktop application, so before you review this guide, see Enhance for Windows 10.

Note

This guide assumes that you've created a Windows app package for your desktop application by using the Desktop Bridge. If you haven't yet done this, see Desktop Bridge.

If you're ready, let's start.

First, setup your Solution

Add one or more UWP projects and runtime components to your solution.

Start with a solution that contains a Windows Application Packaging Project with a reference to your desktop application.

This image shows an example solution.

Extend start project

If your solution doesn't contain a packaging project, see Package your app by using Visual Studio.

Add a UWP project

Add a Blank App (Universal Windows) to your solution.

This is where you'll build a modern XAML UI or use APIs that run only within a UWP process.

UWP project

In your packaging project, right-click the Applications node, and then click Add Reference.

Reference UWP Project

Then, add a reference the UWP project.

Reference UWP Project

Your solution will look something like this:

Solution with UWP project

(Optional) Add a Windows Runtime Component

To accomplish some scenarios, you'll have to add code to a Windows Runtime Component.

runtime component app service

Then, from your UWP project, add a reference to the runtime component. Your solution will look something like this:

Runtime Component Reference

Let's take a look at a few things you can do with your UWP projects and runtime components.

Show a modern XAML UI

As part of your application flow, you can incorporate modern XAML-based user interfaces into your desktop application. These user interfaces are naturally adaptive to different screen sizes and resolutions and support modern interactive models such as touch and ink.

For example, with a small amount of XAML markup, you can give users with powerful map-related visualization features.

This image shows a VB6 application that opens a XAML-based modern UI that contains a map control.

adaptive-design

Have a closer look at this app

✔️ Watch a video

✔️ Get the app

✔️ Browse the code

The design pattern

To show a XAML-based UI, do these things:

1️⃣ Add a protocol extension to that project

2️⃣ Start the UWP app from your desktop app

3️⃣ In the UWP project, show the page that you want

Add a protocol extension

In Solution Explorer, open the package.appxmanifest file of the UWP project in your solution, and add this extension.

<Extensions>
      <uap:Extension
          Category="windows.protocol"
          Executable="MapUI.exe"
          EntryPoint=" MapUI.App">
        <uap:Protocol Name="desktopbridgemapsample" />
      </uap:Extension>
    </Extensions>     

Give the protocol a name, provide the name of the executable produced by the UWP project, and the name of the entry point class.

You can also open the package.appxmanifest in the designer, choose the Declarations tab, and then add the extension there.

declarations-tab

Note

Map controls download data from the internet so if you use one, you'll have to add the "internet client" capability to your manifest as well.

Start the UWP app

First, from your desktop application, create a Uri that includes the protocol name and any parameters you want to pass into the UWP app. Then, call the LaunchUriAsync method.

Here's a basic example in C#.


private async void showMap(double lat, double lon)
{
    string str = "desktopbridgemapsample://";

    Uri uri = new Uri(str + "location?lat=" +
        lat.ToString() + "&?lon=" + lon.ToString());

    var success = await Windows.System.Launcher.LaunchUriAsync(uri);

    if (success)
    {
        // URI launched
    }
    else
    {
        // URI launch failed
    }
}

In our sample, we're doing something a bit more indirect. We've wrapped the call in a VB6-callable interop function named LaunchMap. That function is written by using C++.

Here's the VB block:

Private Declare Function LaunchMap Lib "UWPWrappers.dll" _
  (ByVal lat As Double, ByVal lon As Double) As Boolean

Private Sub EiffelTower_Click()
    LaunchMap 48.858222, 2.2945
End Sub

Here's the C++ function:


DllExport bool __stdcall LaunchMap(double lat, double lon)
{
  try
  {
    String ^str = ref new String(L"desktopbridgemapsample://");
    Uri ^uri = ref new Uri(
      str + L"location?lat=" + lat.ToString() + L"&?lon=" + lon.ToString());

    // now launch the UWP component
    Launcher::LaunchUriAsync(uri);
  }
  catch (Exception^ ex) { return false; }
  return true;
}

Parse parameters and show a page

In the App class of your UWP project, override the OnActivated event handler. If the app is activated by your protocol, parse the parameters and then open the page that you want.

void App::OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs^ e)
{
  if (e->Kind == ActivationKind::Protocol)
  {
    ProtocolActivatedEventArgs^ protocolArgs = (ProtocolActivatedEventArgs^)e;
    Uri ^uri = protocolArgs->Uri;
    if (uri->SchemeName == "desktopbridgemapsample")
    {
      Frame ^rootFrame = ref new Frame();
      Window::Current->Content = rootFrame;
      rootFrame->Navigate(TypeName(MainPage::typeid), uri->Query);
      Window::Current->Activate();
    }
  }
}

Similar Samples

Northwind sample: End-to-end example for UWA UI & Win32 legacy code

Northwind sample: UWP app connecting to SQL Server

Provide services to other apps

You add a service that other apps can consume. For example, you can add a service that gives other apps controlled access to the database behind your app. By implementing a background task, apps can reach the service even if your desktop app is not running.

Here's a sample that does this.

adaptive-design

Have a closer look at this app

✔️ Watch a video

✔️ Get the app

✔️ Browse the code

The design pattern

To show provide a service, do these things:

1️⃣ Implement the app service

2️⃣ Add an app service extension

3️⃣ Test the app service

Implement the app service

Here's where you'll validate and handle requests from other apps. Add this code to a Windows Runtime Component in your solution.

public sealed class AppServiceTask : IBackgroundTask
{
    private BackgroundTaskDeferral backgroundTaskDeferral;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        this.backgroundTaskDeferral = taskInstance.GetDeferral();
        taskInstance.Canceled += OnTaskCanceled;
        var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
        details.AppServiceConnection.RequestReceived += OnRequestReceived;
    }

    private async void OnRequestReceived(AppServiceConnection sender,
                                         AppServiceRequestReceivedEventArgs args)
    {
        var messageDeferral = args.GetDeferral();
        ValueSet message = args.Request.Message;
        string id = message["ID"] as string;
        ValueSet returnData = DataBase.GetData(id);
        await args.Request.SendResponseAsync(returnData);
        messageDeferral.Complete();
    }


    private void OnTaskCanceled(IBackgroundTaskInstance sender,
                                BackgroundTaskCancellationReason reason)
    {
        if (this.backgroundTaskDeferral != null)
        {
            this.backgroundTaskDeferral.Complete();
        }
    }
}

Add an app service extension to the UWP project

Open the package.appxmanifest file of the UWP project, and add an app service extension to the <Application> element.

<Extensions>
      <uap:Extension
          Category="windows.appService"
          EntryPoint="AppServiceComponent.AppServiceTask">
        <uap:AppService Name="com.microsoft.samples.winforms" />
      </uap:Extension>
    </Extensions>    

Give the app service a name and provide the name of the entry point class. This is the class in which you implemented the service.

Test the app service

Test your service by calling it from another app. This code can be a desktop application such as a Windows forms app or another UWP app.

Note

This code only works if you properly set the PackageFamilyName property of the AppServiceConnection class. You can get that name by calling Windows.ApplicationModel.Package.Current.Id.FamilyName in the context of the UWP project. See Create and consume an app service.

private async void button_Click(object sender, RoutedEventArgs e)
{
    AppServiceConnection dataService = new AppServiceConnection();
    dataService.AppServiceName = "com.microsoft.samples.winforms";
    dataService.PackageFamilyName = "Microsoft.SDKSamples.WinformWithAppService";

    var status = await dataService.OpenAsync();
    if (status == AppServiceConnectionStatus.Success)
    {
        string id = int.Parse(textBox.Text);
        var message = new ValueSet();
        message.Add("ID", id);
        AppServiceResponse response = await dataService.SendMessageAsync(message);

        if (response.Status == AppServiceResponseStatus.Success)
        {
            if (response.Message["Status"] as string == "OK")
            {
                DisplayResult(response.Message["Result"]);
            }
        }
    }
}

Learn more about app services here: Create and consume an app service.

Similar Samples

App service bridge sample

App service bridge sample with C++ win32 app

MFC application that receives push notifications

Making your desktop application a share target

You can make your desktop application a share target so that users can easily share data such as pictures from other apps that support sharing.

For example, users could choose your app to share pictures from Microsoft Edge, the Photos app. Here's a WPF sample app that has that capability.

share target

Have a closer look at this app

✔️ Watch a video

✔️ Get the app

✔️ Browse the code

The design pattern

To make your application a share target, do these things:

1️⃣ Add a share target extension

2️⃣ Override the OnNavigatedTo event handler

Add a share target extension

In Solution Explorer, open the package.appxmanifest file of the UWP project in your solution and add the extension.

<Extensions>
      <uap:Extension
          Category="windows.shareTarget"
          Executable="ShareTarget.exe"
          EntryPoint="ShareTarget.App">
        <uap:ShareTarget>
          <uap:SupportedFileTypes>
            <uap:SupportsAnyFileType />
          </uap:SupportedFileTypes>
          <uap:DataFormat>Bitmap</uap:DataFormat>
        </uap:ShareTarget>
      </uap:Extension>
</Extensions>  

Provide the name of the executable produced by the UWP project, and the name of the entry point class. You'll also have to specify what types of files can be shared with your app.

Override the OnNavigatedTo event handler

Override the OnNavigatedTo event handler in the App class of your UWP project.

This event handler is called when users choose your app to share their files.

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
  this.shareOperation = (ShareOperation)e.Parameter;
  if (this.shareOperation.Data.Contains(StandardDataFormats.StorageItems))
  {
      this.sharedStorageItems =
        await this.shareOperation.Data.GetStorageItemsAsync();

      foreach (StorageFile item in this.sharedStorageItems)
      {
          ProcessSharedFile(item);
      }
  }
}

Create a background task

You add a background task to run code even when the app is suspended. Background tasks are great for small tasks that don't require the user interaction. For example, your task can download mail, show a toast notification about an incoming chat message, or react to a change in a system condition.

Here's a WPF sample app that registers a background task.

background task

The task makes an http request and measures the time that it takes for the request to return a response. Your tasks will likely be much more interesting, but this sample is great for learning the basic mechanics of a background task.

Have a closer look at this app

✔️ Browse the code

The design pattern

To create a background service, do these things:

1️⃣ Implement the background task

2️⃣ Configure the background task

3️⃣ Register the background task

Implement the background task

Implement the background task by adding code to a Windows Runtime component project.

public sealed class SiteVerifier : IBackgroundTask
{
    public async void Run(IBackgroundTaskInstance taskInstance)
    {

        taskInstance.Canceled += TaskInstance_Canceled;
        BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
        var msg = await MeasureRequestTime();
        ShowToast(msg);
        deferral.Complete();
    }

    private async Task<string> MeasureRequestTime()
    {
        string msg;
        try
        {
            var url = ApplicationData.Current.LocalSettings.Values["UrlToVerify"] as string;
            var http = new HttpClient();
            Stopwatch clock = Stopwatch.StartNew();
            var response = await http.GetAsync(new Uri(url));
            response.EnsureSuccessStatusCode();
            var elapsed = clock.ElapsedMilliseconds;
            clock.Stop();
            msg = $"{url} took {elapsed.ToString()} ms";
        }
        catch (Exception ex)
        {
            msg = ex.Message;
        }
        return msg;
    }

Configure the background task

In the manifest designer, open the package.appxmanifest file of the UWP project in your solution.

In the Declarations tab, add a Background Tasks declaration.

Background task option

Then, choose the desired properties. Our sample uses the Timer property.

Timer property

Provide the fully qualified name of the class in your Windows Runtime Component that implements the background task.

Timer property

Register the background task

Add code to your desktop application project that registers the background task.

public void RegisterBackgroundTask(String triggerName)
{
    var current = BackgroundTaskRegistration.AllTasks
        .Where(b => b.Value.Name == triggerName).FirstOrDefault().Value;

    if (current is null)
    {
        BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
        builder.Name = triggerName;
        builder.SetTrigger(new MaintenanceTrigger(15, false));
        builder.TaskEntryPoint = "HttpPing.SiteVerifier";
        builder.Register();
        System.Diagnostics.Debug.WriteLine("BGTask registered:" + triggerName);
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("Task already:" + triggerName);
    }
}

Support and feedback

Find answers to your questions

Have questions? Ask us on Stack Overflow. Our team monitors these tags. You can also ask us here.

Give feedback or make feature suggestions

See UserVoice.