Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Paketerade och uppackade skrivbordsappar kan skicka interaktiva app meddelanden precis som UWP-appar (Universal Windows Platform). Det inkluderar paketerade appar (se Skapa ett nytt projekt för ett paketerat WinUI 3-skrivbord app); paketerade appar med extern plats (se Bevilja paketidentitet genom att paketera med extern plats) och packa upp appar (se Skapa ett nytt projekt för ett uppackat WinUI 3-skrivbord app).
För ett oinnehållet skrivbord app finns det dock några särskilda steg. Det beror på de varierande aktiveringsscheman och bristen på paketidentitet under körning.
Note
Termen "toast meddelande" ersätts med "app notification". Båda dessa termer refererar till samma funktion i Windows, men med tiden kommer vi att fasa ut användningen av "toast meddelande" i dokumentationen.
Important
Om du skriver en UWP appkan du läsa UWP-dokumentationen. För andra skrivbordsspråk, se Desktop C#.
Steg 1: Aktivera Windows SDK
Om du inte har aktiverat Windows SDK för din appmåste du göra det först. Det finns några viktiga steg.
- Lägg till ytterligare beroenden 
runtimeobject.libtill . - Inrikta dig på Windows SDK.
 
Högerklicka på projektet och välj Egenskaper.
På den översta konfigurationsmenyn väljer du Alla konfigurationer så att följande ändring tillämpas på både Felsökning och Version.
Under Linker –> Inputlägger du till runtimeobject.lib i Ytterligare beroenden.
Under Allmäntkontrollerar du sedan att Windows SDK Version är inställd på version 10.0 eller senare.
Steg 2: Kopiera kod för kompatibilitetsbibliotek
Kopiera filen DesktopNotificationManagerCompat.h och DesktopNotificationManagerCompat.cpp från GitHub till projektet. Kompatibilitetsbiblioteket sammanfattar mycket av komplexiteten i skrivbordsmeddelanden. Följande instruktioner kräver kompatibilitetsbiblioteket.
Om du använder förkompilerade rubriker, se till att lägga till #include "stdafx.h" på första raden i filen DesktopNotificationManagerCompat.cpp.
Steg 3: Inkludera huvudfilerna och namnrymderna
Inkludera kompatibilitetsbibliotekets huvudfil och huvudfilerna och namnrymderna som är relaterade till att använda API:erna för Windows-meddelanden.
#include "DesktopNotificationManagerCompat.h"
#include <NotificationActivationCallback.h>
#include <windows.ui.notifications.h>
using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
Steg 4: Implementera aktivatorn
Du måste implementera en hanterare för app-meddelandeaktivering, så att när användaren klickar på din notis kan app göra något. Detta krävs för att meddelandet ska sparas i Åtgärdscenter (eftersom meddelandet kan klickas flera dagar senare när ditt app är stängt). Den här klassen kan placeras var som helst i projektet.
Implementera INotificationActivationCallback-gränssnittet enligt nedan, inklusive ett UUID, och anropa även CoCreatableClass- för att flagga klassen som COM-kreabil. För din UUID skapar du ett unikt GUID med hjälp av en av de många online-GUID-generatorerna. Detta GUID CLSID (klassidentifierare) används av Action Center för att identifiera vilken klass som COM ska aktivera.
// The UUID CLSID must be unique to your app. Create a new GUID if copying this code.
class DECLSPEC_UUID("replaced-with-your-guid-C173E6ADF0C3") NotificationActivator WrlSealed WrlFinal
    : public RuntimeClass<RuntimeClassFlags<ClassicCom>, INotificationActivationCallback>
{
public:
    virtual HRESULT STDMETHODCALLTYPE Activate(
        _In_ LPCWSTR appUserModelId,
        _In_ LPCWSTR invokedArgs,
        _In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
        ULONG dataCount) override
    {
        // TODO: Handle activation
    }
};
// Flag class as COM creatable
CoCreatableClass(NotificationActivator);
Steg 5: Registrera dig med meddelandeplattformen
Sedan måste du registrera dig på meddelandeplattformen. Det finns olika steg beroende på om din app är förpackad eller oförpackad. Om du stöder båda måste du utföra båda stegen (men du behöver inte förgrena koden eftersom vårt bibliotek hanterar det åt dig).
Packaged
Om ditt app paket är paketerat (se Skapa ett nytt projekt för ett paketerat WinUI 3-skrivbord app) eller paketerat med extern plats (se Bevilja paketidentitet genom att paketera med extern plats), eller om du stöder båda, lägger du till följande i Package.appxmanifest :
- Deklaration för xmlns:com
 - Deklaration för xmlns:desktop
 - I attributet IgnorableNamespaces finns com och desktop
 - 
              com:Extension för COM-aktivatorn med hjälp av GUID från steg 4. Se till att inkludera 
Arguments="-ToastActivated"så att du vet att din start kom från ett app meddelande - desktop:Extension för windows.toastNotificationActivation för att deklarera din app CLSID för notifikationsaktivering (GUID från steg #4).
 
Package.appxmanifest
<Package
  ...
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  IgnorableNamespaces="... com desktop">
  ...
  <Applications>
    <Application>
      ...
      <Extensions>
        <!--Register COM CLSID LocalServer32 registry key-->
        <com:Extension Category="windows.comServer">
          <com:ComServer>
            <com:ExeServer Executable="YourProject\YourProject.exe" Arguments="-ToastActivated" DisplayName="Toast activator">
              <com:Class Id="replaced-with-your-guid-C173E6ADF0C3" DisplayName="Toast activator"/>
            </com:ExeServer>
          </com:ComServer>
        </com:Extension>
        <!--Specify which CLSID to activate when toast clicked-->
        <desktop:Extension Category="windows.toastNotificationActivation">
          <desktop:ToastNotificationActivation ToastActivatorCLSID="replaced-with-your-guid-C173E6ADF0C3" /> 
        </desktop:Extension>
      </Extensions>
    </Application>
  </Applications>
 </Package>
Unpackaged
Om ditt app är utan paket (se Skapa ett nytt projekt för ett uppackat WinUI 3-skrivbord app), eller om du stöder båda, måste du deklarera ditt Application User Model ID (AUMID) och toast aktiverarens CLSID (GUID från steg #4) på Start-menyns genväg för app.
Välj en unik AUMID som identifierar din app. Detta är vanligtvis i form av [CompanyName]. [AppName]. Men du vill se till att det är unikt för alla appar (så lägg gärna till några siffror i slutet).
Steg 5.1: WiX Installer
Om du använder WiX för installationsprogrammet redigerar du filen Product.wxs för att lägga till de två genvägsegenskaperna i genvägen till Start-menyn enligt nedan. Se till att ditt GUID från steg 4 är inneslutet i {}, som visas nedan.
Product.wxs
<Shortcut Id="ApplicationStartMenuShortcut" Name="Wix Sample" Description="Wix Sample" Target="[INSTALLFOLDER]WixSample.exe" WorkingDirectory="INSTALLFOLDER">
                    
    <!--AUMID-->
    <ShortcutProperty Key="System.AppUserModel.ID" Value="YourCompany.YourApp"/>
    
    <!--COM CLSID-->
    <ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{replaced-with-your-guid-C173E6ADF0C3}"/>
    
</Shortcut>
Important
För att faktiskt kunna använda meddelanden måste du först installera din app med installationsprogrammet innan du felsöker normalt, för att försäkra att Start-genvägen med din AUMID och CLSID är närvarande. När genvägen Start finns kan du felsöka med F5 från Visual Studio.
Steg 5.2: Registrera AUMID- och COM-server
Oavsett installationsprogrammet anropar du sedan metoden app i startkoden (innan du anropar några aviserings-API:er) och anger din meddelandeaktiveringsklass från steg 4 och AUMID som används ovan.
// Register AUMID and COM server (for a packaged app, this is a no-operation)
hr = DesktopNotificationManagerCompat::RegisterAumidAndComServer(L"YourCompany.YourApp", __uuidof(NotificationActivator));
Om du app har stöd för både paketerad och uppackad distribution kan du anropa den här metoden oavsett. Om du kör paketerade applikationer (dvs. med paketidentitet vid körning) kommer denna metod att returnera omedelbart utan att göra någonting. Du behöver inte förgrena koden.
Med den här metoden kan du anropa kompatibilitets-API:er för att skicka och hantera meddelanden utan att ständigt behöva ange din AUMID. Och den infogar registernyckeln LocalServer32 för COM-servern.
Steg 6: Registrera COM-aktivator
För både paketerade och uppackade appar måste du registrera din meddelandeaktiveringstyp så att du kan hantera toast aktiveringar.
I startkoden appanropar du följande RegisterActivator-metod . Detta måste anropas för att du ska kunna ta emot några toast aktiveringar.
// Register activator type
hr = DesktopNotificationManagerCompat::RegisterActivator();
Steg 7: Skicka ett meddelande
Att skicka ett meddelande är identiskt med UWP-appar, förutom att du använder DesktopNotificationManagerCompat för att skapa en ToastNotifier. Kompatibilitetsbiblioteket hanterar automatiskt skillnaden mellan paketerade och uppackade appar, så du behöver inte förgrena koden. För ett uppackat app, cachelagrar kompatibilitetsbiblioteket den AUMID som du angav när du anropade RegisterAumidAndComServer, så att du inte behöver oroa dig för när du ska ange eller inte ange AUMID.
Se till att du använder ToastGeneric-bindningen enligt nedan, eftersom de äldre Windows 8.1-meddelandemallarna toast inte aktiverar COM-meddelandeaktivatorn som du skapade i steg 4.
Important
Http-avbildningar stöds endast i paketerade appar som har internetfunktionen i sitt manifest. Uppackade appar stöder inte http-bilder. Du måste ladda ned bilden till dina lokala app data och referera till den lokalt.
// Construct XML
ComPtr<IXmlDocument> doc;
hr = DesktopNotificationManagerCompat::CreateXmlDocumentFromString(
    L"<toast><visual><binding template='ToastGeneric'><text>Hello world</text></binding></visual></toast>",
    &doc);
if (SUCCEEDED(hr))
{
    // See full code sample to learn how to inject dynamic text, buttons, and more
    // Create the notifier
    // Desktop apps must use the compat method to create the notifier.
    ComPtr<IToastNotifier> notifier;
    hr = DesktopNotificationManagerCompat::CreateToastNotifier(¬ifier);
    if (SUCCEEDED(hr))
    {
        // Create the notification itself (using helper method from compat library)
        ComPtr<IToastNotification> toast;
        hr = DesktopNotificationManagerCompat::CreateToastNotification(doc.Get(), &toast);
        if (SUCCEEDED(hr))
        {
            // And show it!
            hr = notifier->Show(toast.Get());
        }
    }
}
Important
Skrivbordsappar kan inte använda äldre toast mallar (till exempel ToastText02). Aktiveringen av de äldre mallarna misslyckas när COM CLSID har angetts. Du måste använda Windows ToastGeneric-mallarna enligt ovan.
Steg 8: Hantera aktivering
När användaren klickar på meddelandet app eller knapparna i meddelandet anropas metoden Aktivera i klassen NotificationActivator .
I metoden Activate kan du parsa de argument som du angav i meddelandet och hämta den användarindata som användaren skrev in eller valt, och sedan aktivera dina app i enlighet med detta.
Note
Metoden Aktivera anropas på en separat tråd från huvudtråden.
// The GUID must be unique to your app. Create a new GUID if copying this code.
class DECLSPEC_UUID("replaced-with-your-guid-C173E6ADF0C3") NotificationActivator WrlSealed WrlFinal
    : public RuntimeClass<RuntimeClassFlags<ClassicCom>, INotificationActivationCallback>
{
public: 
    virtual HRESULT STDMETHODCALLTYPE Activate(
        _In_ LPCWSTR appUserModelId,
        _In_ LPCWSTR invokedArgs,
        _In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
        ULONG dataCount) override
    {
        std::wstring arguments(invokedArgs);
        HRESULT hr = S_OK;
        // Background: Quick reply to the conversation
        if (arguments.find(L"action=reply") == 0)
        {
            // Get the response user typed.
            // We know this is first and only user input since our toasts only have one input
            LPCWSTR response = data[0].Value;
            hr = DesktopToastsApp::SendResponse(response);
        }
        else
        {
            // The remaining scenarios are foreground activations,
            // so we first make sure we have a window open and in foreground
            hr = DesktopToastsApp::GetInstance()->OpenWindowIfNeeded();
            if (SUCCEEDED(hr))
            {
                // Open the image
                if (arguments.find(L"action=viewImage") == 0)
                {
                    hr = DesktopToastsApp::GetInstance()->OpenImage();
                }
                // Open the app itself
                // User might have clicked on app title in Action Center which launches with empty args
                else
                {
                    // Nothing to do, already launched
                }
            }
        }
        if (FAILED(hr))
        {
            // Log failed HRESULT
        }
        return S_OK;
    }
    ~NotificationActivator()
    {
        // If we don't have window open
        if (!DesktopToastsApp::GetInstance()->HasWindow())
        {
            // Exit (this is for background activation scenarios)
            exit(0);
        }
    }
};
// Flag class as COM creatable
CoCreatableClass(NotificationActivator);
För att ordentligt stödja att bli startad när din 
// Main function
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLineArgs, _In_ int)
{
    RoInitializeWrapper winRtInitializer(RO_INIT_MULTITHREADED);
    HRESULT hr = winRtInitializer;
    if (SUCCEEDED(hr))
    {
        // Register AUMID and COM server (for a packaged app, this is a no-operation)
        hr = DesktopNotificationManagerCompat::RegisterAumidAndComServer(L"WindowsNotifications.DesktopToastsCpp", __uuidof(NotificationActivator));
        if (SUCCEEDED(hr))
        {
            // Register activator type
            hr = DesktopNotificationManagerCompat::RegisterActivator();
            if (SUCCEEDED(hr))
            {
                DesktopToastsApp app;
                app.SetHInstance(hInstance);
                std::wstring cmdLineArgsStr(cmdLineArgs);
                // If launched from toast
                if (cmdLineArgsStr.find(TOAST_ACTIVATED_LAUNCH_ARG) != std::string::npos)
                {
                    // Let our NotificationActivator handle activation
                }
                else
                {
                    // Otherwise launch like normal
                    app.Initialize(hInstance);
                }
                app.RunMessageLoop();
            }
        }
    }
    return SUCCEEDED(hr);
}
Aktiveringssekvens av händelser
Aktiveringssekvensen är följande...
Om din app redan kör:
- Aktivera i din NotificationActivator används
 
Om din app inte fungerar:
- Din app-fil har startats som EXE, du får kommandoradsargumentet med "-ToastActivated"
 - Aktivera i din NotificationActivator används
 
Förgrunds- versus bakgrundsaktivering
För skrivbordsappar hanteras förgrunds- och bakgrundsaktivering på samma sätt – din COM-aktivator anropas. Det är upp till din appkod att bestämma om du vill visa ett fönster eller bara utföra lite arbete och sedan avsluta. Att ange en aktiveringTyp av bakgrund i meddelandeinnehållet app ändrar därför inte beteendet.
Steg 9: Ta bort och hantera meddelanden
Att ta bort och hantera meddelanden är identiskt med UWP-appar. Vi rekommenderar dock att du använder vårt kompatibilitetsbibliotek för att få en DesktopNotificationHistoryCompat så att du inte behöver bekymra dig om att tillhandahålla AUMID för ett skrivbord app.
std::unique_ptr<DesktopNotificationHistoryCompat> history;
auto hr = DesktopNotificationManagerCompat::get_History(&history);
if (SUCCEEDED(hr))
{
    // Remove a specific toast
    hr = history->Remove(L"Message2");
    // Clear all toasts
    hr = history->Clear();
}
Steg 10: Distribuera och felsöka
För att distribuera och felsöka ditt paketerade app, se Kör, felsök och testa ett paketerat skrivbordsapp.
Om du vill distribuera och felsöka skrivbordet appmåste du installera ditt app via installationsprogrammet en gång innan du felsöker normalt, så att genvägen Starta med AUMID och CLSID finns. När genvägen Start finns kan du felsöka med F5 från Visual Studio.
Om dina meddelanden helt enkelt inte visas på skrivbordet app (och inga undantag utlöses) innebär det sannolikt att genvägen Start inte finns (installera din app via installationsprogrammet) eller att den AUMID som du använde i koden inte matchar AUMID i startgenvägen.
Om dina meddelanden visas men inte sparas i Åtgärdscenter (försvinner när popup-fönstret har stängts) innebär det att du inte har implementerat COM-aktivatorn korrekt.
Om du har installerat både den paketerade och uppackade skrivbordsappen app, bör du tänka på att den paketerade app applikationen ersätter den uppackade app när du hanterar toast aktiveringar. Det innebär att app meddelanden från uppackningen app startar paketerade app när du klickar. Om du avinstallerar den paketerade app återställs aktiveringarna till den uppackade app.
Om du får HRESULT 0x800401f0 CoInitialize has not been called., ska du se till att anropa CoInitialize(nullptr) i app innan du anropar API:erna.
Om du får HRESULT 0x8000000e A method was called at an unexpected time. när du anropar Compat-API:erna innebär det förmodligen att du inte kunde anropa de registermetoder som krävs (eller om en paketerad app, kör du för närvarande inte din app under den paketerade kontexten).
Om du får många kompileringsfel för unresolved external symbol har du förmodligen glömt att lägga till runtimeobject.lib i Ytterligare beroenden i steg 1 (eller så har du kanske bara lagt till det i Debugläge och inte i Release-läge).
Hantera äldre versioner av Windows
Om du stöder Windows 8.1 eller lägre vill du under runtime kontrollera om du kör i Windows innan du anropar DesktopNotificationManagerCompat API:er eller skickar ToastGeneric-meddelanden.
Windows 8 introducerade toast meddelanden, men använde äldre toast mallar, till exempel ToastText01. Aktiveringen hanterades av den minnesinterna Aktiverad-händelsen på ToastNotification-klassen eftersom toastarna bara var korta popup-meddelanden som inte bevarades. Windows 10 introducerade interaktiva ToastGeneric-notifikationeroch även Åtgärdscenter där meddelanden sparas i flera dagar. För att införa Åtgärdscenter krävdes en COM-aktivator, så att din toast kan bli aktiverad dagar efter att du skapade den.
| OS | ToastGeneric | COM activator | Äldre toast mallar | 
|---|---|---|---|
| Windows 10 och senare | Supported | Supported | Stöds (men aktiverar inte COM-servern) | 
| Windows 8.1 / 8 | N/A | N/A | Supported | 
| Windows 7 och lägre | N/A | N/A | N/A | 
Om du vill kontrollera om du kör Windows 10 eller senare, inkludera <VersionHelpers.h>-huvudet och kontrollera metoden IsWindows10OrGreater. Om det returnerar truefortsätter du att anropa alla metoder som beskrivs i den här dokumentationen.
#include <VersionHelpers.h>
if (IsWindows10OrGreater())
{
    // Running on Windows 10 or later, continue with sending toasts!
}
Known issues
ÅTGÄRDAT: App blir inte fokuserat efter att ha toastklickat på : I versionerna 15063 och tidigare överfördes inte förgrundsrättigheter till ditt program när vi aktiverade COM-servern. Därför skulle din app bara blinka när du försökte föra den till förgrunden. Det fanns ingen lösning på det här problemet. Vi har åtgärdat detta i versionerna 16299 eller senare.
Resources
Windows developer