Freigeben über


Öffnen eines Diensts

Bevor Ihre Anwendung Vorgänge für einen Dienst ausführen kann, z. B. das Auflisten von Inhalten oder das Abrufen von Beschreibungen unterstützter Ereignisse oder Methoden, muss sie den Dienst öffnen. In der WpdServicesApiSample-Anwendung wird diese Aufgabe im Modul ServiceEnumeration.cpp mithilfe der in der folgenden Tabelle beschriebenen Schnittstellen veranschaulicht.

Schnittstelle Beschreibung
IPortableDeviceServiceManager Wird verwendet, um die Dienste auf einem Gerät aufzulisten.
IPortableDeviceService Wird verwendet, um eine Verbindung mit einem Gerätedienst zu öffnen.
IPortableDeviceValues Wird verwendet, um die Clientinformationen der Anwendung zu enthalten.

 

Die Methode, die einen Dienst öffnet, ist IPortableDeviceService::Open. Diese Methode verwendet zwei Argumente: einen Plug-and-Play-Bezeichner (PnP) für den Dienst und ein IPortableDeviceValues-Objekt , das die Clientinformationen der Anwendung enthält.

Um einen PnP-Bezeichner für einen bestimmten Dienst abzurufen, ruft Ihre Anwendung die IPortableDeviceServiceManager::GetDeviceServices-Methode auf. Diese Methode ruft ein Array von PnP-Bezeichnern für Dienste einer Dienstkategorie-GUID (z. B. SERVICE-Kontakte) ab.

Die Dienstbeispielanwendung ruft einen PnP-Bezeichner für Contacts-Dienste innerhalb der EnumerateContactsServices-Methode im Modul ServiceEnumeration.cpp ab. Das folgende Codebeispiel stammt aus dieser Methode.

// For each device found, find the contacts service
for (dwIndex = 0; dwIndex < cPnpDeviceIDs; dwIndex++)
{
    DWORD   cPnpServiceIDs = 0;
    PWSTR   pPnpServiceID  = NULL;

    // First, pass NULL as the PWSTR array pointer to get the total number
    // of contacts services (SERVICE_Contacts) found on the device.
    // To find the total number of all services on the device, use GUID_DEVINTERFACE_WPD_SERVICE.
    hr = pServiceManager->GetDeviceServices(pPnpDeviceIDs[dwIndex], SERVICE_Contacts, NULL, &cPnpServiceIDs);
    
    if (SUCCEEDED(hr) && (cPnpServiceIDs > 0))
    {                               
        // For simplicity, we are only using the first contacts service on each device
        cPnpServiceIDs = 1;
        hr = pServiceManager->GetDeviceServices(pPnpDeviceIDs[dwIndex], SERVICE_Contacts, &pPnpServiceID, &cPnpServiceIDs);

        if (SUCCEEDED(hr))
        {
            // We've found the service, display it and save its PnP Identifier
            ContactsServicePnpIDs.Add(pPnpServiceID);

            printf("[%d] ", static_cast<DWORD>(ContactsServicePnpIDs.GetCount()-1));

            // Display information about the device that contains this service.
            DisplayDeviceInformation(pServiceManager, pPnpServiceID);

            // ContactsServicePnpIDs now owns the memory for this string
            pPnpServiceID = NULL;
        }
        else
        {
            printf("! Failed to get the first contacts service from '%ws, hr = 0x%lx\n",pPnpDeviceIDs[dwIndex],hr);
        }
    }
}

Nachdem Ihre Anwendung den PnP-Bezeichner für den Dienst abgerufen hat, kann sie die Clientinformationen einrichten und IPortableDeviceService::Open aufrufen.

In der Beispielanwendung wird diese Methode in ChooseDeviceService im Modul ServiceEnumeration.cpp aufgerufen.

IPortableDeviceService unterstützt zwei CLSIDs für CoCreateInstance. CLSID_PortableDeviceService gibt einen IPortableDeviceService-Zeiger zurück, der den Freethread-Marshaller nicht aggregiert. CLSID_PortableDeviceServiceFTM ist eine neue CLSID, die einen IPortableDeviceService-Zeiger zurückgibt, der den Freethread-Marshaller aggregiert. Beide Zeiger unterstützen andernfalls dieselbe Funktionalität.

Anwendungen, die sich in Single Threaded Apartments befinden, sollten CLSID_PortableDeviceServiceFTM verwenden, da dadurch der Mehraufwand für die Schnittstellenzeigermarinierung entfällt. CLSID_PortableDeviceService wird weiterhin für Legacyanwendungen unterstützt.

hr = CoCreateInstance(CLSID_PortableDeviceServiceFTM,
                      NULL,
                      CLSCTX_INPROC_SERVER,
                      IID_PPV_ARGS(&pService));
if (SUCCEEDED(hr))
{
    hr = pService->Open(ContactsServicesArray[uiCurrentService], pClientInformation);
    if (FAILED(hr))
    {
        if (hr == E_ACCESSDENIED)
        {
            printf("Failed to Open the service for Read Write access, will open it for Read-only access instead\n");

            pClientInformation->SetUnsignedIntegerValue(WPD_CLIENT_DESIRED_ACCESS, GENERIC_READ);

            hr = pService->Open(ContactsServicesArray[uiCurrentService], pClientInformation);

            if (FAILED(hr))
            {
                printf("! Failed to Open the service for Read access, hr = 0x%lx\n",hr);
            }
        }
        else
        {
            printf("! Failed to Open the service, hr = 0x%lx\n",hr);
        }
    }

IPortableDeviceService-Schnittstelle

IPortableDeviceValues-Schnittstelle

IPortableDeviceServiceManager-Schnittstelle

WpdServicesApiSample