Condividi tramite


Implementare un provider di feed in un'app win32 (C++/WinRT)

Nota

Alcune informazioni sono relative a un prodotto non definitivo, che potrebbe subire modifiche sostanziali prima del rilascio sul mercato. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Questo articolo illustra come creare un provider di feed semplice che registra un URI del contenuto del feed e implementa l'interfaccia IFeedProvider. I metodi di questa interfaccia vengono richiamati dalla scheda Widget per richiedere parametri di stringa di query personalizzati, in genere per supportare gli scenari di autenticazione. I provider di feed possono supportare un singolo feed o multipli feed.

Per implementare un provider di feed con C++/WinRT, vedere Implementare un provider di feed in un'app C# Windows (C++/WinRT).

Prerequisiti

  • Il dispositivo deve avere la modalità sviluppatore abilitata. Per altre informazioni, vedere Impostazioni per gli sviluppatori.
  • Visual Studio 2022 o versioni successive con il carico di lavoro Sviluppo per la piattaforma UWP (Universal Windows Platform). Assicurarsi di aggiungere il componente per C++ (v143) dall'elenco a discesa facoltativo.

Creare una nuova app console win32 C++/WinRT

In Visual Studio creare un nuovo progetto. Nella finestra di dialogo Crea un nuovo progetto impostare il filtro del linguaggio su "C++" e il filtro della piattaforma su Windows, quindi selezionare il modello di progetto Applicazione console di Windows (C++/WinRT). Assegnare il nome al nuovo progetto "ExampleFeedProvider". Per questa procedura dettagliata, assicurarsi che sia deselezionato Inserisci soluzione e progetto nella stessa directory. Quando richiesto, impostare la versione di Windows di destinazione per l'app su 10.022631.2787 o versione successiva.

Aggiungere riferimenti ai pacchetti NuGet libreria di implementazione Windows e Windows App SDK

Questo esempio usa il pacchetto NuGet Windows App SDK stabile più recente. In Esplora soluzioni fare clic con il pulsante destro del mouse su Riferimenti e selezionare Gestisci pacchetti NuGet.... Nella gestione pacchetti NuGet, selezionare la scheda Sfoglia e cercare "Microsoft.WindowsAppSDK". Selezionare la versione stabile più recente nell'elenco a discesa Versione e quindi fare clic su Installa.

Questo esempio usa anche il pacchetto NuGet libreria di implementazione Windows. In Esplora soluzioni fare clic con il pulsante destro del mouse su Riferimenti e selezionare Gestisci pacchetti NuGet.... Nella gestione pacchetti NuGet, selezionare la scheda Sfoglia e cercare "Microsoft.Windows.ImplementationLibrary". Selezionare la versione più recente nell'elenco a discesa Versione e quindi fare clic su Installa.

Nel file di intestazione precompilato pch.h aggiungere le direttive di inclusione seguenti.

//pch.h 
#pragma once
#include <wil/cppwinrt.h>
#include <wil/resource.h>
...
#include <winrt/Microsoft.Windows.Widgets.Providers.h>

Nota

È necessario includere prima l'intestazione wil/cppwinrt.h e successivamente di qualsiasi intestazione WinRT.

Per gestire correttamente l'arresto dell'app del provider di feed, è necessario un'implementazione personalizzata di winrt::get_module_lock. Emettiamo una predichiarazione del metodo SignalLocalServerShutdown che viene definito nel file main.cpp e impostiamo un evento che segnala l'uscita dall'app. Aggiungere il codice seguente al file pch.h, subito sotto la direttiva #pragma once prima dell'inclusione dell'altro.

//pch.h
#include <stdint.h>
#include <combaseapi.h>

// In .exe local servers the class object must not contribute to the module ref count, and use
// winrt::no_module_lock, the other objects must and this is the hook into the C++ WinRT ref counting system
// that enables this.
void SignalLocalServerShutdown();

namespace winrt
{
    inline auto get_module_lock() noexcept
    {
        struct service_lock
        {
            uint32_t operator++() noexcept
            {
                return ::CoAddRefServerProcess();
            }

            uint32_t operator--() noexcept
            {
                const auto ref = ::CoReleaseServerProcess();

                if (ref == 0)
                {
                    SignalLocalServerShutdown();
                }
                return ref;
            }
        };

        return service_lock{};
    }
}


#define WINRT_CUSTOM_MODULE_LOCK

Aggiungere una classe FeedProvider per gestire le operazioni del feed

In Visual Studio, fare clic con il pulsante destro del mouse sul progetto ExampleFeedProvider in Esplora soluzioni e selezionare Aggiungi->Classe. Nella finestra di dialogo Aggiungi classe, assegnare alla classe il nome "FeedProvider" e fare clic su Aggiungi.

Dichiarare una classe che implementa l'interfaccia IFeedProvider

L'interfaccia IFeedProvider definisce i metodi che la scheda Widget richiama per avviare operazioni con il provider di feed. Sostituire la definizione di classe vuota nel file FeedProvider.h con il codice seguente. Questo codice dichiara una struttura che implementa l'interfaccia IFeedProvider e dichiara i prototipi per i metodi di interfaccia.

// FeedProvider.h
#pragma once
struct FeedProvider : winrt::implements<FeedProvider, winrt::Microsoft::Windows::Widgets::Feeds::Providers::IFeedProvider>
{
    FeedProvider() {}

    /* IFeedrovider required functions that need to be implemented */
    void OnFeedProviderEnabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedProviderEnabledArgs args);
    void OnFeedProviderDisabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedProviderDisabledArgs args);
    void OnFeedEnabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedEnabledArgs args);
    void OnFeedDisabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedDisabledArgs args);
    void OnCustomQueryParametersRequested(winrt::Microsoft::Windows::Widgets::Feeds::Providers::CustomQueryParametersRequestedArgs args);
    /* IFeedProvider required functions that need to be implemented */

};

Implementare i metodi IFeedProvider

Nelle sezioni successive verranno implementati i metodi dell'interfaccia IFeedProvider. Prima di approfondire i metodi di interfaccia, aggiungere le righe seguenti a FeedProvider.cpp, dopo le direttive di inclusione, per eseguire il pull delle API del provider di feed nello spazio dei nomi winrt e consentire l'accesso alla mappa dichiarata nel passaggio precedente.

Nota

Gli oggetti passati nei metodi di callback dell'interfaccia IFeedProvider sono garantiti solo per essere validi all'interno del callback. Non è consigliabile archiviare riferimenti a questi oggetti perché il relativo comportamento all'esterno del contesto del callback non è definito.

// WidgetProvider.cpp
namespace winrt
{
    using namespace Microsoft::Windows::Widgets::Feeds::Providers;
}

OnFeedProviderEnabled

Il metodo OnFeedProviderEnabled viene richiamato quando un feed associato al provider viene creato dall'host della scheda Widget. Nell'implementazione di questo metodo generare una stringa di query con i parametri che verranno passati all'URL che fornisce il contenuto del feed, inclusi i token di autenticazione necessari. Creare un'istanza di CustomQueryParametersUpdateOptions, passando in FeedProviderDefinitionId dagli argomenti dell'evento che identificano il feed abilitato e la stringa di query. Ottenere il FeedManager e chiamare SetCustomQueryParameters per registrare i parametri della stringa di query con la scheda Widget.

// FeedProvider.cs
void FeedProvider::OnFeedProviderEnabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedProviderEnabledArgs args)
{
    std::wstringstream wstringstream;
wstringstream << args.FeedProviderDefinitionId().c_str() << L" feed provider was enabled." << std::endl;
    _putws(wstringstream.str().c_str());

    auto updateOptions = winrt::CustomQueryParametersUpdateOptions(args.FeedProviderDefinitionId(), L"param1&param2");
    winrt::FeedManager::GetDefault().SetCustomQueryParameters(updateOptions);
}

OnFeedProviderDisabled

OnFeedProviderDisabled viene chiamato nella scheda Widget quando tutti i feed per questo provider sono stati disabilitati. I provider di feed non devono eseguire alcuna azione in risposta a questa chiamata al metodo. La chiamata al metodo può essere usata per scopi di telemetria o per aggiornare i parametri della stringa di query o revocare i token di autenticazione, se necessario. Se l'app supporta solo un singolo provider di feed o se tutti i provider di feed supportati dall'app sono stati disabilitati, l'app può uscire in risposta a questo callback.

// FeedProvider.cs

void FeedProvider::OnFeedProviderDisabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedProviderDisabledArgs args)
{
    std::wstringstream wstringstream;
    wstringstream << args.FeedProviderDefinitionId().c_str() << L" feed provider was disabled." << std::endl;
    _putws(wstringstream.str().c_str());
}

OnFeedEnabled, OnFeedDisabled

OnFeedEnabled e OnFeedDisabled vengono richiamati dalla scheda Widget quando un feed è abilitato o disabilitato. I provider di feed non devono eseguire alcuna azione in risposta a queste chiamate al metodo. La chiamata al metodo può essere usata per scopi di telemetria o per aggiornare i parametri della stringa di query o revocare i token di autenticazione, se necessario.

// FeedProvider.cs

void FeedProvider::OnFeedEnabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedEnabledArgs args)
{
    std::wstringstream wstringstream;
    wstringstream << args.FeedDefinitionId().c_str() << L" feed was enabled." << std::endl;
    _putws(wstringstream.str().c_str());
}
// FeedProvider.cs

void FeedProvider::OnFeedDisabled(winrt::Microsoft::Windows::Widgets::Feeds::Providers::FeedDisabledArgs args)
{
    std::wstringstream wstringstream;
    wstringstream << args.FeedDefinitionId().c_str() << L" feed was disabled." << std::endl;
    _putws(wstringstream.str().c_str());
}

OnCustomQueryParametersRequested

OnCustomQueryParametersRequested viene generato quando la scheda Widget determina che i parametri di query personalizzati associati al provider di feed devono essere aggiornati. Ad esempio, questo metodo può essere generato se l'operazione per recuperare il contenuto del feed dal servizio Web remoto ha esito negativo. La proprietà FeedProviderDefinitionId di CustomQueryParametersRequestedArgs passata a questo metodo specifica il feed per il quale vengono richiesti parametri della stringa di query. Il provider deve rigenerare la stringa di query e passarla nuovamente alla scheda Widget chiamando SetCustomQueryParameters.

// FeedProvider.cs

void FeedProvider::OnCustomQueryParametersRequested(winrt::Microsoft::Windows::Widgets::Feeds::Providers::CustomQueryParametersRequestedArgs args)
{
    std::wstringstream wstringstream;
    wstringstream << L"CustomQueryParameters were requested for " << args.FeedProviderDefinitionId().c_str() << std::endl;
    _putws(wstringstream.str().c_str());

    auto updateOptions = winrt::CustomQueryParametersUpdateOptions(args.FeedProviderDefinitionId(), L"param1&param2");
    winrt::FeedManager::GetDefault().SetCustomQueryParameters(updateOptions);
}

Registrare una class factory che creerà un'istanza di FeedProvider su richiesta

Aggiungere l'intestazione che definisce la classe FeedProvider alle inclusioni nella parte superiore del file dell'app main.cpp. Qui verrà incluso anche mutex.

// main.cpp
...
#include "FeedProvider.h"
#include <mutex>

Dichiarare l'evento che attiverà l'uscita dell'app e la funzione SignalLocalServerShutdown che imposta l'evento. Incollare il codice seguente in main.cpp.

// main.cpp
wil::unique_event g_shudownEvent(wil::EventOptions::None);

void SignalLocalServerShutdown()
{
    g_shudownEvent.SetEvent();
}

Successivamente, sarà necessario creare un CLSID che verrà usato per identificare il provider di feed per l'attivazione COM. Generare un GUID in Visual Studio passando a Strumenti->Crea GUID. Selezionare l'opzione "static const GUID =" e fare clic su Copia, quindi incollare in main.cpp. Aggiornare la definizione GUID con la sintassi C++/WinRT seguente, impostando il nome della variabile GUID feed_provider_clsid. Lasciare la versione con commenti del GUID, perché sarà necessario questo formato in un secondo momento, quando si crea il pacchetto dell'app.

// main.cpp
...
// {80F4CB41-5758-4493-9180-4FB8D480E3F5}
static constexpr GUID feed_provider_clsid
{
    0x80f4cb41, 0x5758, 0x4493, { 0x91, 0x80, 0x4f, 0xb8, 0xd4, 0x80, 0xe3, 0xf5 }
};

Aggiungere la definizione della class factory seguente main.cpp. Si tratta principalmente di codice boilerplate non specifico per le implementazioni del provider di feed. Nota: CoWaitForMultipleObjects attende che l'evento di arresto venga attivato prima dell'uscita dall'app.

// main.cpp
template <typename T>
struct SingletonClassFactory : winrt::implements<SingletonClassFactory<T>, IClassFactory>
{
    STDMETHODIMP CreateInstance(
        ::IUnknown* outer,
        GUID const& iid,
        void** result) noexcept final
    {
        *result = nullptr;

        std::unique_lock lock(mutex);

        if (outer)
        {
            return CLASS_E_NOAGGREGATION;
        }

        if (!instance)
        {
            instance = winrt::make<FeedProvider>();
        }

        return instance.as(iid, result);
    }

    STDMETHODIMP LockServer(BOOL) noexcept final
    {
        return S_OK;
    }

private:
    T instance{ nullptr };
    std::mutex mutex;
};

int main()
{
    winrt::init_apartment();
    wil::unique_com_class_object_cookie feedProviderFactory;
    auto factory = winrt::make<SingletonClassFactory<winrt::Microsoft::Windows::Widgets::Feeds::Providers::IFeedProvider>>();

    winrt::check_hresult(CoRegisterClassObject(
        feed_provider_clsid,
        factory.get(),
        CLSCTX_LOCAL_SERVER,
        REGCLS_MULTIPLEUSE,
        feedProviderFactory.put()));

    DWORD index{};
    HANDLE events[] = { g_shudownEvent.get() };
    winrt::check_hresult(CoWaitForMultipleObjects(CWMO_DISPATCH_CALLS | CWMO_DISPATCH_WINDOW_MESSAGES,
        INFINITE,
        static_cast<ULONG>(std::size(events)), events, &index));

    return 0;
}

Creare un pacchetto dell'app del provider di feed

Nella versione corrente, solo le app in pacchetto possono essere registrate come provider di feed. La procedura seguente illustra il processo di creazione del pacchetto dell'app e l'aggiornamento del manifesto dell'app per registrare l'app con il sistema operativo come provider di feed.

Creare un progetto di creazione di pacchetti MSIX

In Esplora soluzioni fare clic con il pulsante destro del mouse sulla soluzione e selezionare Aggiungi->Nuovo progetto.... Nella finestra di dialogo Aggiungi un nuovo progetto selezionare il modello "Progetto di creazione pacchetti per applicazioni Windows" e fare clic su Avanti. Impostare il nome progetto "ExampleFeedProviderPackage" e fare clic su Crea. Quando richiesto, impostare la versione di destinazione alla versione 1809 o versione successiva e fare clic su OK. Quindi fare clic con il pulsante destro del mouse sul progetto ExampleFeedProviderPackage e selezionare Aggiungi->Riferimento progetto. Selezionare il progetto ExampleFeedProvider e fare clic su OK.

Aggiungere il riferimento pacchetto Windows App SDK al progetto di creazione del pacchetto

È necessario aggiungere un riferimento al pacchetto nuget Windows App SDK al progetto di creazione pacchetti MSIX. In Esplora soluzioni, fare doppio clic sul progetto ExampleFeedProviderPackage per aprire il file ExampleFeedProviderPackage.wapproj. Aggiungere il codice XML seguente all'interno dell'elemento Project.

<!--ExampleFeedProviderPackage.wapproj-->
<ItemGroup>
    <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231116003-experimentalpr">
        <IncludeAssets>build</IncludeAssets>
    </PackageReference>  
</ItemGroup>

Nota

Assicurarsi che la Versione specificata nell'elemento PackageReference corrisponda alla versione stabile più recente a cui si fa riferimento nel passaggio precedente.

Se la versione corretta di Windows App SDK è già installata nel computer e non si vuole aggregare il runtime SDK nel pacchetto, è possibile specificare la dipendenza del pacchetto nel file Package.appxmanifest per il progetto ExampleFeedProviderPackage.

<!--Package.appxmanifest-->
...
<Dependencies>
...
    <PackageDependency Name="Microsoft.WindowsAppRuntime.1.5.233430000-experimental1" MinVersion="2000.638.7.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
...
</Dependencies>
...

Aggiornare il manifesto del pacchetto

In Esplora soluzioni fare clic con il pulsante destro del mouse sul Package.appxmanifest file e selezionare Visualizza codice per aprire il file XML del manifesto. Successivamente è necessario aggiungere alcune dichiarazioni dello spazio dei nomi per le estensioni del pacchetto dell'app che verranno usati. Aggiungere le definizioni dello spazio dei nomi seguenti all'elemento Pacchetto di livello superiore.

<!-- Package.appmanifest -->
<Package
  ...
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"

All'interno dell'elemento Applicazione creare un nuovo elemento vuoto denominato Estensioni. Assicurarsi che venga dopo il tag di chiusura per uap:VisualElements.

<!-- Package.appxmanifest -->
<Application>
...
    <Extensions>

    </Extensions>
</Application>

La prima estensione da aggiungere è l'estensione ComServer. In questo modo viene registrato il punto di ingresso del file eseguibile con il sistema operativo. Questa estensione è l'app in pacchetto equivalente alla registrazione di un server COM impostando una chiave del registro di sistema e non è specifica per i provider di feed. Aggiungere l'elemento com:Extension seguente come elemento figlio dell'elemento Estensioni. Modificare il GUID nell'attributo Id dell'elemento com:Class impostando il GUID generato in un passaggio precedente.

<!-- Package.appxmanifest -->
<Extensions>
    <com:Extension Category="windows.comServer">
        <com:ComServer>
            <com:ExeServer Executable="ExampleFeedProvider\ExampleFeedProvider.exe" Arguments="-RegisterProcessAsComServer" DisplayName="C++ Feed Provider App">
                <com:Class Id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" DisplayName="FeedProvider" />
            </com:ExeServer>
        </com:ComServer>
    </com:Extension>
</Extensions>

Aggiungere quindi l'estensione che registra l'app come provider di feed. Incollare l'elemento uap3:Extension nel frammento di codice seguente, come elemento figlio dell'elemento Estensioni. Assicurarsi di sostituire l'attributo ClassId dell'elemento COM con il GUID usato nei passaggi precedenti.

<!-- Package.appxmanifest -->
<Extensions>
    ...
    <uap3:Extension Category="windows.appExtension">
        <uap3:AppExtension Name="com.microsoft.windows.widgets.feeds" DisplayName="ContosoFeed" Id="com.examplewidgets.examplefeed" PublicFolder="Public">
            <uap3:Properties>
                <FeedProvider Icon="ms-appx:Assets\StoreLogo.png" Description="FeedDescription">
                    <Activation>
                        <!-- Apps exports COM interface which implements IFeedProvider -->
                        <CreateInstance ClassId="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" />
                    </Activation>
                    <Definitions>
                        <Definition Id="Contoso_Feed"
                            DisplayName="Contoso_Feed Feed"
                            Description="Feed representing Contoso"
                            ContentUri="https://www.contoso.com/"
                            Icon="ms-appx:Images\StoreLogo.png">
                        </Definition>
                        <Definition Id="Fabrikam_Feed"
                            DisplayName="Fabrikam Feed"
                            Description="Feed representing Example"
                            ContentUri="https://www.fabrikam.com/"
                            Icon="ms-appx:Images\StoreLogo.png">
                        </Definition>
                    </Definitions>
                </FeedProvider>
            </uap3:Properties>
        </uap3:AppExtension>
    </uap3:Extension>
</Extensions>

Per descrizioni dettagliate e informazioni sul formato per tutti questi elementi, vedere Formato XML del manifesto del pacchetto del provider di feed.

Aggiungere icone al progetto di creazione pacchetti

In Esplora soluzioni, fare clic con il pulsante destro del mouse su ExampleFeedProviderPackage e selezionare Aggiungi->Nuova cartella. Denominare questa cartella ProviderAssets perché è ciò che è stato usato in Package.appxmanifest dal passaggio precedente. Qui verrà archiviata l'icona per i feed. Dopo aver aggiunto le icone desiderate, assicurarsi che i nomi delle immagini corrispondano a ciò che viene dopo Path=ProviderAssets\ in Package.appxmanifest o i feed non verranno visualizzati nella scheda Widget.

Test del provider di feed

Assicurarsi di aver selezionato l'architettura corrispondente al computer di sviluppo dall'elenco a discesa Piattaforme soluzione, ad esempio "x64". In Esplora soluzioni, fare clic con il pulsante destro del mouse sulla soluzione e scegliere Compila soluzione. Al termine, fare clic con il pulsante destro del mouse su ExampleWidgetProviderPackage e scegliere Distribuisci. L'app console dovrebbe essere avviata alla distribuzione e i feed verranno abilitati nell'output della console. Aprire la scheda Widget e visualizzare i nuovi feed nelle schede nella parte superiore della sezione feed.

Debug del provider di feed

Dopo aver aggiunto i feed, la piattaforma Widget avvierà l'applicazione del provider di feed per ricevere e inviare informazioni pertinenti sul feed. Per eseguire il debug del feed in esecuzione, è possibile collegare un debugger all'applicazione del provider di feed in esecuzione oppure configurare Visual Studio per avviare automaticamente il debug del processo del provider di feed dopo l'avvio.

Per connettersi al processo in esecuzione:

  1. In Visual Studio fare clic su Debug -> Connetti a processo.
  2. Filtrare i processi e trovare l'applicazione del provider di feed desiderata.
  3. Collegare il debugger.

Per collegare automaticamente il debugger al processo all'avvio iniziale:

  1. In Visual Studio fare clic su Debug -> Altre destinazioni di debug -> Debug pacchetto applicazione installato.
  2. Filtrare i pacchetti e trovare il pacchetto del provider di feed desiderato.
  3. Selezionarlo e selezionare la casella Non avviare, ma eseguire il debug del codice all'avvio.
  4. Scegliere Connetti.

Convertire l'app console in un'app di Windows

Per convertire l'app console creata in questa procedura dettagliata in un'app di Windows:

  1. Fare clic con il pulsante destro del mouse sul progetto ExampleWidgetProvider in Esplora soluzioni e seleziona Proprietà. Passare a Linker -> Sistema e modificare SubSystem da "Console" a "Windows". A tale scopo, è anche possibile aggiungere <Sottosistema>Windows</Sottosistema> a <Collegamento>..</Collegamento> sezione di .vcxproj.
  2. In main.cpp passare int main() a int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR pCmdLine, _In_ int /*nCmdShow*/).

Screenshot che mostra le proprietà del progetto provider di feed C++ con il tipo di output impostato su Applicazione Windows

Pubblicazione dell'app del provider di feed

Dopo aver sviluppato e testato il provider di feed, è possibile pubblicare l'app in Microsoft Store per consentire agli utenti di installare i feed nei propri dispositivi. Per istruzioni dettagliate per la pubblicazione di un'app, consultare Pubblicare l'app in Microsoft Store.

Raccolta dell'archivio feed

Dopo che la tua app è stata pubblicata in Microsoft Store, puoi richiedere che la tua app sia inclusa nella raccolta di feed store che consente agli utenti di individuare le app che presentano feed di Windows. Per inviare la richiesta, vedi Inviare il feed/bacheca per aggiungere la raccolta dello Store.