서비스 열기

애플리케이션이 서비스에 대한 작업을 수행하기 전에(예: 콘텐츠 열거 또는 지원되는 이벤트 또는 메서드에 대한 설명 검색) 서비스를 열어야 합니다. WpdServicesApiSample 애플리케이션에서 이 작업은 다음 표에 설명된 인터페이스를 사용하여 ServiceEnumeration.cpp 모듈에 설명되어 있습니다.

인터페이스 Description
IPortableDeviceServiceManager 디바이스에서 서비스를 열거하는 데 사용됩니다.
IPortableDeviceService 디바이스 서비스에 대한 연결을 여는 데 사용됩니다.
IPortableDeviceValues 애플리케이션의 클라이언트 정보를 보유하는 데 사용됩니다.

 

서비스를 여는 메서드는 IPortableDeviceService::Open입니다. 이 메서드는 서비스에 대한 PnP(플러그 앤 플레이) 식별자와 애플리케이션의 클라이언트 정보를 포함하는 IPortableDeviceValues 개체라는 두 가지 인수를 사용합니다.

지정된 서비스에 대한 PnP 식별자를 가져오기 위해 애플리케이션 은 IPortableDeviceServiceManager::GetDeviceServices 메서드를 호출합니다. 이 메서드는 서비스 범주 GUID(예: SERVICE Contacts)의 서비스에 대한 PnP 식별자 배열을 검색합니다.

샘플 서비스 애플리케이션은 ServiceEnumeration.cpp 모듈의 EnumerateContactsServices 메서드 내에서 Contacts 서비스에 대한 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.cpp 모듈의 ChooseDeviceService 내에서 호출됩니다.

IPortableDeviceServiceCoCreateInstance에 대해 두 개의 CLSID를 지원합니다. CLSID_PortableDeviceService 자유 스레드 마샬러를 집계하지 않는 IPortableDeviceService 포인터를 반환합니다. CLSID_PortableDeviceServiceFTM 자유 스레드 마샬러를 집계하는 IPortableDeviceService 포인터를 반환하는 새 CLSID입니다. 그렇지 않으면 두 포인터 모두 동일한 기능을 지원합니다.

단일 스레드 아파트에 거주하는 애플리케이션은 인터페이스 포인터 마샬링의 오버헤드를 없애기 때문에 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