Chiamare le API di Windows Runtime nelle app desktop

Questo argomento descrive come configurare i progetti di app desktop per l'uso delle API di Windows Runtime (WinRT) fornite dal sistema operativo Windows e per aggiungere esperienze moderne di Windows 11 e Windows 10 alle app desktop.

Alcune API di Windows Runtime (WinRT) non sono supportate nelle app desktop. Per altre informazioni, vedere API di Windows Runtime non supportate nelle app desktop.

Modificare un progetto .NET per l'uso delle API di Windows Runtime

Per i progetti .NET sono disponibili numerose opzioni:

  • A partire da .NET 6 , è possibile specificare il moniker del framework di destinazione (TFM) nel file di progetto per accedere alle API di WinRT. Questa opzione è supportata nei progetti destinati a Windows 10, versione 1809 o successiva.
  • Per le versioni precedenti di .NET, puoi installare il pacchetto NuGet Microsoft.Windows.SDK.Contracts per aggiungere tutti i riferimenti necessari al progetto. Questa opzione è supportata nei progetti destinati a Windows 10, versione 1803 o successiva.
  • Se il progetto è destinato a .NET 6 (o versione successiva) e a versioni precedenti di .NET, è possibile configurare il file di progetto in modo da usare entrambe le opzioni.

.NET 6 e versioni successive: usare l'opzione del moniker framework di destinazione

Questa opzione è supportata solo nei progetti che usano .NET 6 (o versione successiva) e destinati a Windows 10, versione 1809 o una versione del sistema operativo successiva. Specificando un TFM specifico della versione del sistema operativo Windows nel file di progetto, viene aggiunto un riferimento al pacchetto di destinazione Windows SDK appropriato. Per altre informazioni generiche su questo scenario, vedere il post di blog su come chiamare le API di Windows in .NET.

  1. Con il progetto aperto in Visual Studio, fai clic sul progetto con il pulsante destro del mouse in Esplora soluzioni e scegli Modifica file di progetto. Il file di progetto avrà un aspetto simile al seguente.

    Nota

    L'esempio seguente mostra un OutputType con valore WinExe, che specifica un eseguibile della GUI di Windows e impedisce l'apertura di una finestra della console durante l'esecuzione dell'app. Se l'app non ha una GUI, OutputType avrà un valore diverso. È possibile chiamare API di WinRT da app GUI di Windows, app console e librerie. Inoltre, il valore per TargetFramework potrebbe non corrispondere esattamente all'esempio seguente.

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
      </PropertyGroup>
    </Project>
    
  2. Lasciando tutte le altre impostazioni così come sono, sostituire il valore dell'elemento TargetFramework con una delle stringhe seguenti:

    • net6.0-windows10.0.17763.0: se l'app è destinata a Windows 10, versione 1809.
    • net6.0-windows10.0.18362.0: se l'app è destinata a Windows 10, versione 1903.
    • net6.0-windows10.0.19041.0: se l'app è destinata a Windows 10, versione 2004.
    • net6.0-windows10.0.22000.0: se l'app è destinata a Windows 11.

    Ad esempio, l'elemento seguente è relativo a un progetto destinato a Windows 10, versione 2004.

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

    Nelle versioni successive di .NET è possibile sostituire il valore con la versione pertinente, ad esempio net6.0-windows10.0.19041.0.

  3. Salva le modifiche e chiudi il file di progetto.

API WinRT non supportate in .NET 6 o versioni successive

In .NET 6 e versioni successive sono presenti diverse API di Windows Runtime (WinRT) nello spazio dei nomi Windows.UI non supportate. Per le API elencate di seguito esistono versioni equivalenti delle API nello spazio dei nomi WinUI (Microsoft.UI), ad esempio Microsoft.UI.Text. Le API WinRT seguenti non sono supportate in .NET 6 e versioni successive:

  • Classe Windows.UI.Colors
  • Classe Windows.UI.ColorHelper
  • Windows.UI.Text (tutte le classi in questo spazio dei nomi tranneWindows.UI.Text.FontStretch, Windows.UI.Text.FontStyle, Windows.UI.Text.FontWeight, Windows.UI.Text.UnderlineType e tutte le classi nello spazio dei nomi Windows.UI.Text.Core)
  • Windows.UI.Xaml (tutte le classi in questo spazio dei nomi)

Supporto di più versioni del sistema operativo Windows

La proprietà TargetFramework specifica della versione del sistema operativo Windows determina la versione di Windows SDK con cui viene compilata l'app. Questa proprietà determina il set di API accessibili in fase di compilazione e fornisce valori predefiniti per TargetPlatformVersion e TargetPlatformMinVersion (se non impostato in modo esplicito). Non occorre definire la proprietà TargetPlatformVersion in modo esplicito nel file di progetto, perché viene impostata automaticamente dalla versione del sistema operativo TargetFramework.

Il valore TargetPlatformMinVersion può essere sottoposto a override in modo che sia minore di TargetPlatformVersion (determinato dalla versione nella proprietà TargetFramework). Questo consente l'esecuzione di un'app in versioni precedenti del sistema operativo. Ad esempio, è possibile impostare quanto segue nel file di progetto in modo che l'app supporti Windows 10, versione 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>

Si noti che impostando TargetPlatformMinVersion su una versione inferiore TargetPlatformVersion si crea la possibilità che vengano chiamate API non disponibili. Quando si chiamano API di WinRT non disponibili in tutte le versioni del sistema operativo supportate, è consigliabile usare ApiInformation per controllare queste chiamate. Per altre informazioni, vedere App adattive per la versione.

Versioni precedenti di .NET: installare il pacchetto NuGet Microsoft.Windows.SDK.Contracts

Usare questa opzione se l'app usa .NET Core 3.x o .NET Framework. Questa opzione è supportata nei progetti destinati a Windows 10, versione 1803 o successiva.

  1. Assicurati che i riferimenti ai pacchetti siano abilitati:

    1. In Visual Studio fare clic su Strumenti -> Gestione pacchetti NuGet -> Impostazioni di Gestione pacchetti.
    2. Verifica che PackageReference sia selezionato per Formato di gestione pacchetti predefinito.
  2. Con il progetto aperto in Visual Studio, fai clic sul progetto con il pulsante destro del mouse in Esplora soluzioni e scegli Gestisci pacchetti NuGet.

  3. Nella finestra Gestione pacchetti NuGet seleziona la scheda Sfoglia e cerca Microsoft.Windows.SDK.Contracts.

  4. Dopo aver trovato il pacchetto Microsoft.Windows.SDK.Contracts, nel riquadro destro della finestra Gestione pacchetti NuGet seleziona la Versione del pacchetto da installare in base alla versione di Windows 10 di destinazione:

    • 10.0.19041.xxxx: scegliere questa opzione per Windows 10 versione 2004.
    • 10.0.18362.xxxx: scegliere questa opzione per Windows 10 versione 1903.
    • 10.0.17763.xxxx: scegliere questa opzione per Windows 10 versione 1809.
    • 10.0.17134.xxxx: scegliere questa opzione per Windows 10 versione 1803.
  5. Fare clic su Installa.

Configurare progetti destinati a più versioni diverse di .NET

Se il progetto è destinato a .NET 6 (o versione successiva) e a versioni precedenti (inclusi .NET Core 3.x e .NET Framework), è possibile configurare il file di progetto in modo da usare il moniker del framework di destinazione (TFM) per il pull automatico dei riferimenti alle API WinRT per .NET 6 e usare il pacchetto NuGet Microsoft.Windows.SDK.Contracts per le versioni precedenti.

  1. Con il progetto aperto in Visual Studio, fai clic sul progetto con il pulsante destro del mouse in Esplora soluzioni e scegli Modifica file di progetto. L'esempio seguente illustra un file di progetto per un'app che usa .NET Core 3.1.

    Nota

    L'esempio seguente mostra un OutputType con valore WinExe, che specifica un eseguibile della GUI di Windows e impedisce l'apertura di una finestra della console durante l'esecuzione dell'app. Se l'app non ha una GUI, OutputType avrà un valore diverso. È possibile chiamare API di WinRT da app GUI di Windows, app console e librerie. Inoltre, il valore per TargetFramework potrebbe non corrispondere esattamente all'esempio seguente.

    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <UseWindowsForms>true</UseWindowsForms>
      </PropertyGroup>
    </Project>
    
  2. Sostituisci l'elemento TargetFramework nel file con un elemento TargetFrameworks (nota il plurale). In questo elemento specificare i moniker framework di destinazione (TFM) per tutte le versioni di .NET di destinazione, separati da punti e virgola.

    • Per .NET 6 o versioni successive, usare uno dei moniker framework di destinazione seguenti:
      • net6.0-windows10.0.17763.0: se l'app è destinata a Windows 10, versione 1809.
      • net6.0-windows10.0.18362.0: se l'app è destinata a Windows 10, versione 1903.
      • net6.0-windows10.0.19041.0: se l'app è destinata a Windows 10, versione 2004.
    • Per .NET Core 3.x, usa netcoreapp3.0 o netcoreapp3.1.
    • Per .NET Framework, usare net46.

    Nell'esempio seguente viene illustrato come usare più destinazioni .NET Core 3.1 e .NET 6 (per Windows 10, versione 2004).

    <TargetFrameworks>netcoreapp3.1;net6.0-windows10.0.19041.0</TargetFrameworks>
    
  3. Dopo l'elemento PropertyGroup, aggiungere un elemento PackageReference che includa un'istruzione condizionale che installa il pacchetto NuGet Microsoft.Windows.SDK.Contracts per tutte le versioni di .NET Core 3.x o .NET Framework a cui è destinata l'app. L'elemento PackageReference deve essere figlio di un elemento ItemGroup. L'esempio seguente illustra come eseguire questa operazione per .NET Core 3.1.

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

    Al termine, il file di progetto avrà un aspetto simile al seguente.

    <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. Salva le modifiche e chiudi il file di progetto.

Modificare un progetto desktop C++ (Win32) per l'uso delle API di Windows Runtime

Usare C++/WinRT per utilizzare le API WinRT. C++/WinRT è una proiezione del linguaggio C++ 17 interamente standard e moderna per le API WinRT, implementata come libreria basata su file di intestazione e progettata per fornire accesso privilegiato alla moderna API di Windows.

Per configurare il progetto per C++/WinRT:

Per informazioni dettagliate su queste opzioni, vedere Supporto di Visual Studio per C++/WinRT e VSIX.

Aggiungere le esperienze di Windows 10

Ora sei pronto per aggiungere esperienze moderne e accattivanti per gli utenti che eseguono la tua applicazione in Windows 10. Usa questo flusso di progettazione.

Per prima cosa, decidi quali esperienze vuoi aggiungere

Ce ne sono molte tra cui scegliere. Ad esempio, puoi semplificare il flusso di ordine di acquisto tramite le API di monetizzazione o richiamare l'attenzione sulla tua applicazione quando hai qualcosa di interessante da condividere, come una nuova immagine pubblicata da un altro utente.

Toast notification

Anche se gli utenti ignorano il tuo messaggio, possono vederlo nuovamente nel centro notifiche e quindi fare clic sul messaggio per aprire la tua app. Questo aumenta l'interesse per la tua applicazione e ha il vantaggio aggiuntivo di rendere visivamente l'applicazione molto integrata con il sistema operativo. Ti mostreremo il codice per questa esperienza più avanti in questo articolo.

Per altre idee, fai riferimento alla documentazione della piattaforma UWP.

Decidi se migliorare o estendere

Sentirai spesso usare i termini migliorare ed estendere, quindi ci prendiamo un po' di tempo per spiegare esattamente ciò che significa ciascun termine.

Usiamo il termine migliorare per descrivere le API WinRT che è possibile chiamare direttamente dall'app desktop, che si tratti o meno di app in pacchetto. Quando hai scelto un'esperienza di Windows 10, identifica le API necessarie per crearla e quindi verifica se l'API viene visualizzata in questo elenco. Questo è l'elenco delle API che puoi chiamare direttamente dall'app desktop. Se l'API non viene visualizzata nell'elenco, la funzionalità associata all'API può essere eseguita solo all'interno di un processo UWP. Spesso, sono incluse le API che eseguono il rendering di XAML UWP, ad esempio un controllo mappa UWP o una richiesta di Windows Hello.

Nota

Benché le API che eseguono il rendering di XAML UWP in genere non possano essere chiamate direttamente dal desktop, potresti usare approcci alternativi. Se vuoi ospitare controlli XAML UWP o altre esperienze visive personalizzate, puoi usare le isole XAML (a partire da Windows 10 versione 1903) e il livello visivo (a partire da Windows 10 versione 1803). Queste funzionalità possono essere usate in app desktop incluse o meno in un pacchetto.

Se si è scelto di inserire l'app desktop in un pacchetto, un'altra opzione consiste nell'estendere l'applicazione aggiungendo un progetto UWP alla soluzione. Il progetto desktop è ancora il punto di ingresso dell'applicazione, ma il progetto UWP consente di accedere a tutte le API che non sono visualizzate in questo elenco. L'app desktop può comunicare con il processo UWP mediante un servizio app e sono disponibili numerose indicazioni per configurare questa integrazione. Se vuoi aggiungere un'esperienza che richiede un progetto UWP, vedi Estendere con i componenti UWP.

Contratti API di riferimento

Se puoi chiamare l'API direttamente dall'app desktop, apri un browser e cerca l'argomento di riferimento per l'API in questione. Sotto il riepilogo dell'API, troverai una tabella che descrive il contratto API corrispondente. Ecco un esempio di tabella:

API contract table

Se hai un'app desktop basata su .NET, aggiungi un riferimento al contratto API e quindi imposta la proprietà Copia localmente del file su False. Se hai un progetto C++, aggiungi alle tue Directory di inclusione aggiuntive un percorso della cartella che contiene il contratto.

Chiama le API per aggiungere l'esperienza

Ecco il codice che usi per visualizzare la finestra di notifica che abbiamo esaminato in precedenza. Queste API sono presenti in questo elenco e quindi puoi aggiungere questo codice all'app desktop ed eseguirlo al momento.

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));
}

Per altre informazioni sulle notifiche, vedi Notifiche di tipo avviso popup adattive e interattive.

Supporto per basi di installazione Windows XP, Windows Vista e Windows 7/8

Puoi modernizzare l'applicazione per Windows 10 senza dover creare un nuovo ramo e mantenere separate le basi di codice.

Se vuoi creare file binari separati per gli utenti di Windows 10, usa la compilazione condizionale. Se preferisci creare un set di file binari da distribuire a tutti gli utenti di Windows, usa i controlli di runtime.

Diamo un'occhiata veloce a ciascuna opzione.

Compilazione condizionale

Puoi mantenere una base di codice e compilare un set di file binari solo per gli utenti di Windows 10.

Per prima cosa, aggiungi una nuova configurazione di compilazione al progetto.

Build Configuration

Per questa configurazione di compilazione, creare una costante per identificare il codice che chiama le API WinRT.

Per i progetti basati su .NET, la costante viene chiamata costante di compilazione condizionale.

Conditional Compilation constant

Per i progetti basati su C++, la costante viene chiamata definizione per il preprocessore.

Preprocessor Definition constant

Aggiungi la costante prima di qualsiasi blocco di codice UWP.

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

Il compilatore compila il codice solo se la costante è definita nella configurazione di compilazione attiva.

controlli di runtime

Puoi compilare un set di file binari per tutti gli utenti di Windows, indipendentemente dalla versione di Windows eseguita. L'applicazione chiama le API WinRT solo se l'utente esegue l'applicazione come applicazione in pacchetto in Windows 10.

Il modo più semplice per aggiungere controlli di runtime al codice consiste nell'installare il pacchetto NuGet Desktop Bridge Helpers e quindi usare il metodo IsRunningAsUWP() per escludere tutto il codice che chiama le API WinRT. Per altri dettagli, vedere questo post di blog: Desktop Bridge - Identificare il contesto dell'applicazione.

Trova le risposte alle tue domande

Altre domande? Partecipa a Stack Overflow. Il nostro team controlla costantemente questi tag. È anche possibile porre domande nei forum.