Dela via


Anropa Windows Runtime-API:er i skrivbordsappar

Det här avsnittet beskriver hur du konfigurerar dina skrivbordsappprojekt så att de använder Windows Runtime-API:er (WinRT) som tillhandahålls av Windows-operativsystemet och för att lägga till moderna Windows 11- och Windows 10-upplevelser i dina skrivbordsappar.

Vissa Windows Runtime-API:er (WinRT) stöds inte i skrivbordsappar. Mer information finns i Windows Runtime-API:er som inte stöds i skrivbordsappar.

Ändra ett .NET-projekt för att använda Windows Runtime-API:er

Det finns flera alternativ för .NET-projekt:

  • Från och med .NET 6 kan du ange Target Framework Moniker (TFM) i projektfilen för att få åtkomst till WinRT-API:er. Det här alternativet stöds i projekt som riktar sig mot Windows 10, version 1809 eller senare.
  • För tidigare versioner av .NET kan du installera Microsoft.Windows.SDK.Contracts NuGet-paketet för att lägga till alla nödvändiga referenser till projektet. Det här alternativet stöds i projekt som är avsedda för Windows 10, version 1803 eller senare.
  • Om projektet har flera mål för .NET 6 (eller senare) och tidigare versioner av .NET kan du konfigurera projektfilen så att den använder båda alternativen.

.NET 6 och senare: Använd moniker-alternativet Target Framework

Det här alternativet stöds endast i projekt som använder .NET 6 (eller senare) och som mål för Windows 10, version 1809 eller en senare version av operativsystemet. Genom att ange en versionsspecifik TFM för Windows-operativsystemet i projektfilen läggs en referens till i lämpligt Windows SDK-målpaket. Mer bakgrundsinformation om det här scenariot finns i blogginlägget Anropa Windows-API:er i .NET.

  1. När projektet är öppet i Visual Studio högerklickar du på projektet i Solution Explorer och väljer Redigera projektfil. Projektfilen ser ut ungefär så här.

    Anteckning

    Exemplet nedan visar en OutputType- av WinExe, som anger en körbar Windows GUI -fil (och förhindrar att ett konsolfönster öppnas när appen körs). Om din app inte har ett GUI har din OutputType- ett annat värde. Du kan anropa WinRT-API:er från Windows GUI-appar, konsolappar och bibliotek. Dessutom kanske ditt värde för TargetFramework- inte exakt matchar exemplet nedan.

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
      </PropertyGroup>
    </Project>
    
  2. Om du lämnar alla andra inställningar som de är ersätter du värdet för TargetFramework- element med någon av följande strängar:

    • net6.0-windows10.0.17763.0: Om din app riktar sig mot Windows 10 version 1809.
    • net6.0-windows10.0.18362.0: Om din app riktar in sig på Windows 10 version 1903.
    • net6.0-windows10.0.19041.0: Om din app riktar sig mot Windows 10 version 2004.
    • net6.0-windows10.0.22000.0: Om din app riktar in sig på den första versionen av Windows 11.
    • net6.0-windows10.0.22621.0: Om din app riktar in sig på Windows 11 version 22H2.
    • net6.0-windows10.0.26100.0: Om din app riktar sig mot Windows 11 version 24H2.

    Följande element är till exempel för ett projekt som riktar sig till Windows 10, version 2004.

    <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
    

    I senare versioner av .NET kan du ersätta värdet med relevant version, till exempel net8.0-windows10.0.19041.0.

  3. Spara ändringarna och stäng projektfilen.

WinRT-API:er stöds inte i .NET 6 eller senare

I .NET 6 och senare finns det flera Windows Runtime-API:er (WinRT) i Windows.UI- namnområde som inte stöds. För de API:er som anges nedan finns motsvarande versioner av API:erna i namnområdet WinUI (Microsoft.UI) (till exempel Microsoft.UI.Text). Följande WinRT-API:er stöds inte på .NET 6 och senare:

Stöd för flera Windows OS-versioner

Den versionsspecifika windows-operativsystemet TargetFramework-egenskapen avgör vilken version av Windows SDK som appen kompileras med. Den här egenskapen bestämmer uppsättningen tillgängliga API:er vid byggtiden och tillhandahåller standardvärden för både TargetPlatformVersion och TargetPlatformMinVersion- (om den inte anges uttryckligen). Egenskapen TargetPlatformVersion behöver inte definieras uttryckligen i projektfilen, eftersom den anges automatiskt av TargetFramework OS-version.

TargetPlatformMinVersion kan åsidosättas till mindre än TargetPlatformVersion (bestäms av versionen i egenskapen TargetFramework). Detta gör att en app kan köras på tidigare os-versioner. Du kan till exempel ange följande i projektfilen för att stödja appens nednivå till Windows 10, version 1809.

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
   <OutputType>WinExe</OutputType>
   <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
   <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
 </PropertyGroup>
</Project>

Observera att om du anger TargetPlatformMinVersion till en version under TargetPlatformVersion kan du anropa otillgängliga API:er. När du anropar WinRT-API:er som inte är tillgängliga i alla operativsystemversioner som stöds rekommenderar vi att du skyddar dessa anrop med ApiInformation kontroller. Mer information finns i Version av anpassningsbara appar.

Tidigare versioner av .NET: Installera NuGet-paketet Microsoft.Windows.SDK.Contracts

Använd det här alternativet om din app använder .NET Core 3.x eller .NET Framework. Det här alternativet stöds i projekt som är avsedda för Windows 10, version 1803 eller senare.

  1. Kontrollera att paketreferenser är aktiverade:

    1. I Visual Studio klickar du på Tools –> NuGet Package Manager –> Package Manager-inställningar.
    2. Kontrollera att PackageReference har valts för Standardpakethanteringsformat.
  2. När projektet är öppet i Visual Studio högerklickar du på projektet i Solution Explorer och väljer Hantera NuGet-paket.

  3. I fönstret NuGet Package Manager väljer du fliken Bläddra och söker efter Microsoft.Windows.SDK.Contracts.

  4. När Microsoft.Windows.SDK.Contracts-paketet har hittats väljer du version för det paket som du vill installera baserat på den version av Windows 10 som du vill använda i det högra fönstret i fönstret NuGet Package Manager:

    • 10.0.19041.xxxx: Välj detta för Windows 10, version 2004.
    • 10.0.18362.xxxx: Välj detta för Windows 10, version 1903.
    • 10.0.17763.xxxx: Välj detta för Windows 10 version 1809.
    • 10.0.17134.xxxx: Välj detta för Windows 10 version 1803.
  5. Klicka på Installera.

Konfigurera projekt som har flera mål för olika versioner av .NET

Om projektet har flera mål för .NET 6 (eller senare) och tidigare versioner (inklusive .NET Core 3.x och .NET Framework) kan du konfigurera projektfilen att använda Target Framework Moniker (TFM) för att automatiskt hämta WinRT API-referenserna för .NET 6 (eller senare) och använda Microsoft.Windows.SDK.Contracts NuGet-paketet för tidigare versioner.

  1. När projektet är öppet i Visual Studio högerklickar du på projektet i Solution Explorer och väljer Redigera projektfil. I följande exempel visas en projektfil för en app som använder .NET Core 3.1.

    Not

    Exemplet nedan visar en OutputType- av WinExe, som anger en körbar Windows GUI -fil (och förhindrar att ett konsolfönster öppnas när appen körs). Om din app inte har ett GUI har din OutputType- ett annat värde. Du kan anropa WinRT-API:er från Windows GUI-appar, konsolappar och bibliotek. Dessutom kanske ditt värde för TargetFramework- inte exakt matchar exemplet nedan.

    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <UseWindowsForms>true</UseWindowsForms>
      </PropertyGroup>
    </Project>
    
  2. Ersätt elementet TargetFramework i filen med ett TargetFrameworks- element (observera plural). I det här elementet anger du Target Framework Monikers (TFM) för alla versioner av .NET som du vill rikta, avgränsade med semikolon.

    • För .NET 6 eller senare använder du någon av följande Target Framework Monikers (TFM):
      • net6.0-windows10.0.17763.0: Om din app riktar sig mot Windows 10 version 1809.
      • net6.0-windows10.0.18362.0: Om din app riktar in sig på Windows 10 version 1903.
      • net6.0-windows10.0.19041.0: Om din app riktar sig mot Windows 10 version 2004.
      • net6.0-windows10.0.22000.0: Om din app riktar in sig på den första versionen av Windows 11.
      • net6.0-windows10.0.22621.0: Om din app riktar in sig på Windows 11 version 22H2.
      • net6.0-windows10.0.26100.0: Om din app riktar sig mot Windows 11 version 24H2.
    • För .NET Core 3.x använder du netcoreapp3.0 eller netcoreapp3.1.
    • För .NET Framework använder du net46.

    I följande exempel visas hur du använder .NET Core 3.1 och .NET 6 för flera mål (för Windows 10 version 2004).

    <TargetFrameworks>netcoreapp3.1;net6.0-windows10.0.19041.0</TargetFrameworks>
    
  3. Efter elementet PropertyGroup ska du lägga till ett PackageReference-element som innehåller en villkorssats som installerar Microsoft.Windows.SDK.Contracts NuGet-paketet för alla versioner av .NET Core 3.x eller .NET Framework som din app riktar sig mot. Elementet PackageReference måste vara underordnat elementet ItemGroup. I följande exempel visas hur du gör detta för .NET Core 3.1.

    <ItemGroup>
      <PackageReference Condition="'$(TargetFramework)' == 'netcoreapp3.1'"
                        Include="Microsoft.Windows.SDK.Contracts"
                        Version="10.0.19041.0" />
    </ItemGroup>
    

    När du är klar bör projektfilen se ut ungefär så här.

    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFrameworks>netcoreapp3.1;net6.0-windows10.0.19041.0</TargetFrameworks>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
      <ItemGroup>
        <PackageReference Condition="'$(TargetFramework)' == 'netcoreapp3.1'"
                         Include="Microsoft.Windows.SDK.Contracts"
                         Version="10.0.19041.0" />
      </ItemGroup>
    </Project>
    
  4. Spara ändringarna och stäng projektfilen.

Ändra ett C++-skrivbordsprojekt (Win32) för att använda Windows Runtime-API:er

Använd C++/WinRT- för att använda WinRT-API:er. C++/WinRT är en helt standardmodern C++17-språkprojektion för WinRT-API:er, implementerat som ett huvudfilbaserat bibliotek och utformat för att ge dig förstklassig åtkomst till det moderna Windows-API:et.

Så här konfigurerar du projektet för C++/WinRT:

Mer information om de här alternativen finns i Visual Studio-stöd för C++/WinRT och VSIX-.

Lägga till Windows 10-upplevelser

Nu är du redo att lägga till moderna upplevelser som lyser upp när användarna kör ditt program på Windows 10. Använd det här designflödet.

Bestäm först vilka upplevelser du vill lägga till

Det finns mycket att välja mellan. Du kan till exempel förenkla inköpsorderflödet med hjälp av API:er för intäktsgenereringeller direkt uppmärksamhet på ditt program när du har något intressant att dela, till exempel en ny bild som en annan användare har publicerat.

toast-meddelande

Även om användarna ignorerar eller avvisar ditt meddelande kan de se det igen i åtgärdscentret och sedan klicka på meddelandet för att öppna appen. Detta ökar engagemanget för ditt program och har den extra bonusen att få ditt program att verka djupt integrerat med operativsystemet. Vi visar koden för den upplevelsen lite senare i den här artikeln.

Mer information finns i UWP-dokumentationen.

Bestäm om du vill förbättra eller utöka

Du kommer ofta att höra oss använda termerna förbättra och utöka, så vi tar en stund att förklara exakt vad var och en av dessa termer betyder.

Vi använder termen förbättra för att beskriva WinRT-API:er som du kan anropa direkt från din skrivbordsapp oavsett om det är en paketerad app eller inte. När du har valt en Windows 10-upplevelse identifierar du de API:er som du behöver för att skapa den och ser sedan om api:et visas i den här listan. Det här är en lista över API:er som du kan anropa direkt från din skrivbordsapp. Om ditt API inte visas i den här listan beror det på att funktionerna som är associerade med det API:et endast kan köras i en UWP-process. Dessa inkluderar ofta API:er som återger UWP XAML, till exempel en UWP-kartkontroll eller en Windows Hello-säkerhetsprompt.

Not

Även om API:er som renderar UWP XAML vanligtvis inte kan anropas direkt från skrivbordet, kanske du kan använda alternativa metoder. Om du vill vara värd för UWP XAML-kontroller eller andra anpassade visuella funktioner kan du använda XAML Islands (från och med Windows 10, version 1903) och Visual Layer (från och med Windows 10 version 1803). Dessa funktioner kan användas i paketerade eller uppackade desktop-appar.

Om du har valt att paketera din skrivbordsapp är ett annat alternativ att utöka programmet genom att lägga till ett UWP-projekt i din lösning. Skrivbordsprojektet är fortfarande startpunkten för ditt program, men UWP-projektet ger dig åtkomst till alla API:er som inte visas i den här listan. Skrivbordsappen kan kommunicera med UWP-processen med hjälp av en apptjänst och vi har mycket vägledning om hur du konfigurerar den. Om du vill lägga till en upplevelse som kräver ett UWP-projekt kan du läsa Utöka med UWP-komponenter.

REFERENS-API-kontrakt

Om du kan anropa API:et direkt från din skrivbordsapp öppnar du en webbläsare och söker efter referensavsnittet för api:et. Under sammanfattningen av API:et hittar du en tabell som beskriver API-kontraktet för api:et. Här är ett exempel på tabellen:

API-kontraktstabell

Om du har en .NET-baserad skrivbordsapp, lägg till en referens till API-kontraktet och ange sedan egenskapen Kopiera lokal för den filen till False. Om du har ett C++-baserat projekt, lägger du till en sökväg till mappen som innehåller det här kontraktet i dina Ytterligare inkluderingskataloger.

Anropa API:erna för att lägga till din upplevelse

Här är koden som du använder för att visa meddelandefönstret som vi tittade på tidigare. Dessa API:er visas i den här listan så att du kan lägga till den här koden i din skrivbordsapp och köra den just nu.

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

private void ShowToast()
{
    string title = "featured picture of the day";
    string content = "beautiful scenery";
    string image = "https://picsum.photos/360/180?image=104";
    string logo = "https://picsum.photos/64?image=883";

    string xmlString =
    $@"<toast><visual>
       <binding template='ToastGeneric'>
       <text>{title}</text>
       <text>{content}</text>
       <image src='{image}'/>
       <image src='{logo}' placement='appLogoOverride' hint-crop='circle'/>
       </binding>
      </visual></toast>";

    XmlDocument toastXml = new XmlDocument();
    toastXml.LoadXml(xmlString);

    ToastNotification toast = new ToastNotification(toastXml);

    ToastNotificationManager.CreateToastNotifier().Show(toast);
}
#include <sstream>
#include <winrt/Windows.Data.Xml.Dom.h>
#include <winrt/Windows.UI.Notifications.h>

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Notifications;
using namespace winrt::Windows::Data::Xml::Dom;

void UWP::ShowToast()
{
    std::wstring const title = L"featured picture of the day";
    std::wstring const content = L"beautiful scenery";
    std::wstring const image = L"https://picsum.photos/360/180?image=104";
    std::wstring const logo = L"https://picsum.photos/64?image=883";

    std::wostringstream xmlString;
    xmlString << L"<toast><visual><binding template='ToastGeneric'>" <<
        L"<text>" << title << L"</text>" <<
        L"<text>" << content << L"</text>" <<
        L"<image src='" << image << L"'/>" <<
        L"<image src='" << logo << L"'" <<
        L" placement='appLogoOverride' hint-crop='circle'/>" <<
        L"</binding></visual></toast>";

    XmlDocument toastXml;

    toastXml.LoadXml(xmlString.str().c_str());

    ToastNotificationManager::CreateToastNotifier().Show(ToastNotification(toastXml));
}
using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::UI::Notifications;
using namespace Windows::Data::Xml::Dom;

void UWP::ShowToast()
{
    Platform::String ^title = "featured picture of the day";
    Platform::String ^content = "beautiful scenery";
    Platform::String ^image = "https://picsum.photos/360/180?image=104";
    Platform::String ^logo = "https://picsum.photos/64?image=883";

    Platform::String ^xmlString =
        L"<toast><visual><binding template='ToastGeneric'>" +
        L"<text>" + title + "</text>" +
        L"<text>"+ content + "</text>" +
        L"<image src='" + image + "'/>" +
        L"<image src='" + logo + "'" +
        L" placement='appLogoOverride' hint-crop='circle'/>" +
        L"</binding></visual></toast>";

    XmlDocument ^toastXml = ref new XmlDocument();

    toastXml->LoadXml(xmlString);

    ToastNotificationManager::CreateToastNotifier()->Show(ref new ToastNotification(toastXml));
}

Mer information om meddelanden finns i Anpassningsbara och interaktiva toast-aviseringar.

Stöd för installationsbaser för Windows XP, Windows Vista och Windows 7/8

Du kan modernisera ditt program för Windows 10 utan att behöva skapa en ny gren och underhålla separata kodbaser.

Om du vill skapa separata binärfiler för Windows 10-användare använder du villkorlig kompilering. Om du föredrar att skapa en uppsättning binärfiler som du distribuerar till alla Windows-användare, bör du använda körningstidskontroller.

Låt oss ta en snabb titt på varje alternativ.

Villkorsstyrd kompilering

Du kan behålla en kodbas och kompilera en uppsättning binärfiler bara för Windows 10-användare.

Lägg först till en ny byggkonfiguration i projektet.

Byggkonfiguration

För den byggkonfigurationen skapar du en konstant som identifierar kod som anropar WinRT-API:er.

För. NET-baserade projekt kallas konstanten för en villkorlig kompileringskonstant.

konstant för villkorlig kompilering

För C++-baserade projekt kallas konstanten för en förprocessordefinition.

Konstant definition för förprocessor

Lägg till den konstanten före något block med UWP-kod.

[System.Diagnostics.Conditional("_UWP")]
private void ShowToast()
{
 ...
}
#if _UWP
void UWP::ShowToast()
{
 ...
}
#endif

Kompilatorn skapar endast koden om den konstanten definieras i din aktiva byggkonfiguration.

Körningskontroller

Du kan kompilera en uppsättning binärfiler för alla dina Windows-användare oavsett vilken version av Windows de kör. Ditt program anropar endast WinRT-API:er om användaren kör programmet som ett paketerat program i Windows 10.

Det enklaste sättet att lägga till körningskontroller i koden är att installera det här Nuget-paketet: Desktop Bridge Helpers och sedan använda metoden IsRunningAsUWP() för att stänga av all kod som anropar WinRT-API:er. Mer information finns i det här blogginlägget: Desktop Bridge – Identifiera programmets kontext.

Hitta svar på dina frågor

Har du frågor? Fråga oss på Stack Overflow. Vårt team övervakar dessa -tags. Du kan också fråga på våra forum.