打开服务

在您的应用程序可以对服务执行操作(例如,枚举内容或检索支持的事件或方法的说明)之前,它必须打开服务。 在 WpdServicesApiSample 应用程序中,使用下表中所述的接口在 ServiceEnumeration 模块中演示了此任务。

接口 说明
IPortableDeviceServiceManager 用于枚举设备上的服务。
IPortableDeviceService 用于打开到设备服务的连接。
IPortableDeviceValues 用于保存应用程序的客户端信息。

打开服务的方法是 IPortableDeviceService:: Open。 此方法采用两个参数:服务的即插即用 (PnP) 标识符,以及包含应用程序的客户端信息的 IPortableDeviceValues 对象。

若要获取给定服务的 PnP 标识符,你的应用程序将调用 IPortableDeviceServiceManager:: GetDeviceServices 方法。 此方法检索服务类别 GUID 服务的 PnP 标识符数组 (例如服务联系人) 。

示例服务应用程序在 ServiceEnumeration 模块中的 EnumerateContactsServices 方法内检索联系人服务的 PnP 标识符。 下面的代码示例取自此方法。

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

在应用程序检索服务的 PnP 标识符后,它可以设置客户端信息并调用 IPortableDeviceService:: Open

在示例应用程序中,在 ServiceEnumeration 模块中的 ChooseDeviceService 内调用此方法。

IPortableDeviceService 支持用于 CoCreateInstance 的两个 clsid。 CLSID _PortableDeviceService 返回不聚合自由线程封送拆收器的 IPortableDeviceService 指针; CLSID _PortableDeviceServiceFTM 是一个新的 CLSID,它返回聚合自由线程封送拆收器的 IPortableDeviceService 指针。 这两个指针支持相同的功能。

驻留在单线程单元中的应用程序应使用 CLSID _ PortableDeviceServiceFTM ,因为这样可以消除接口指针封送处理的开销。 CLSID _ 旧版应用程序仍支持 PortableDeviceService。

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 接口

IPortableDeviceValues 接口

IPortableDeviceServiceManager 接口

WpdServicesApiSample