Bagikan melalui


Mengatur Properti untuk Beberapa Objek

Beberapa driver perangkat mendukung pengaturan properti untuk beberapa objek dalam satu panggilan fungsi—ini disebut sebagai penulisan massal. Aplikasi Anda dapat melakukan penulisan massal menggunakan antarmuka yang dijelaskan dalam tabel berikut.

Antarmuka Deskripsi
Antarmuka IPortableDeviceContent Menyediakan akses ke metode khusus konten.
Antarmuka IPortableDeviceProperties Menyediakan akses ke metode khusus properti.
Antarmuka IPortableDevicePropertiesBulk Mendukung operasi tulis massal.
Antarmuka IPortableDevicePropVariantCollection Digunakan untuk menyimpan pengidentifikasi objek untuk operasi massal.
Antarmuka IPortableDeviceValuesCollection Digunakan untuk mengidentifikasi properti yang akan ditulis.

 

Fungsi WriteContentPropertiesBulk dalam modul ContentProperties.cpp aplikasi sampel menunjukkan operasi penulisan massal.

Tugas pertama yang dicapai dalam sampel ini adalah menentukan apakah driver yang diberikan mendukung operasi massal atau tidak. Ini dicapai dengan memanggil QueryInterface pada objek IPortableDeviceProperties dan memeriksa keberadaan IPortableDevicePropertiesBulk.

HRESULT                                       hr                = S_OK;
GUID                                          guidContext       = GUID_NULL;
CSetBulkValuesCallback*                       pCallback         = NULL;
CComPtr<IPortableDeviceProperties>            pProperties;
CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
CComPtr<IPortableDeviceValues>                pObjectProperties;
CComPtr<IPortableDeviceContent>               pContent;
CComPtr<IPortableDeviceValuesCollection>      pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD                                         cObjectIDs        = 0;
if (SUCCEEDED(hr))
{
    hr = pDevice->Content(&pContent);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
    }
}



if (SUCCEEDED(hr))
{
    hr = pContent->Properties(&pProperties);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr);
    }
}



if (SUCCEEDED(hr))
{
    hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk));
    if (FAILED(hr))
    {
        printf("This driver does not support BULK property operations.\n");
    }
}

Tugas berikutnya memerlukan pembuatan objek IPortableDeviceValuesCollection . Ini adalah objek yang berisi nilai properti yang akan ditulis sampel.

HRESULT                                       hr                = S_OK;
GUID                                          guidContext       = GUID_NULL;
CSetBulkValuesCallback*                       pCallback         = NULL;
CComPtr<IPortableDeviceProperties>            pProperties;
CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
CComPtr<IPortableDeviceValues>                pObjectProperties;
CComPtr<IPortableDeviceContent>               pContent;
CComPtr<IPortableDeviceValuesCollection>      pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD                                         cObjectIDs        = 0;
if (SUCCEEDED(hr))
{
    hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_IPortableDeviceValuesCollection,
                          (VOID**) &pPropertiesToWrite);
    if (FAILED(hr))
    {
        printf("! Failed to CoCreate IPortableDeviceValuesCollection for bulk property values, hr = 0x%lx\n", hr);
    }
}

Setelah ini, sampel membuat instans antarmuka IPortableDevicePropertiesBulkCallback. Aplikasi akan menggunakan metode dalam antarmuka ini untuk melacak kemajuan operasi penulisan massal asinkron.

HRESULT                                       hr                = S_OK;
GUID                                          guidContext       = GUID_NULL;
CSetBulkValuesCallback*                       pCallback         = NULL;
CComPtr<IPortableDeviceProperties>            pProperties;
CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
CComPtr<IPortableDeviceValues>                pObjectProperties;
CComPtr<IPortableDeviceContent>               pContent;
CComPtr<IPortableDeviceValuesCollection>      pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD                                         cObjectIDs        = 0;
if (SUCCEEDED(hr))
{
    pCallback = new CSetBulkValuesCallback();
    if (pCallback == NULL)
    {
        hr = E_OUTOFMEMORY;
        printf("! Failed to allocate CSetBulkValuesCallback, hr = 0x%lx\n", hr);
    }
}

Fungsi berikutnya yang dipanggil aplikasi sampel adalah fungsi pembantu CreateIPortableDevicePropVariantCollectionWithAllObjectIDs . Fungsi ini secara rekursif menghitung semua objek pada perangkat tertentu dan mengembalikan antarmuka IPortableDevicePropVariantCollection yang berisi pengidentifikasi untuk setiap objek yang ditemukannya. Fungsi ini didefinisikan dalam modul ContentEnumeration.cpp.

// 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs
// to enumerate and create an IPortableDevicePropVariantCollection with the object
// identifiers needed to perform the bulk operation on.
if (SUCCEEDED(hr))
{
    hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pDevice,
                                                                    pContent,
                                                                    &pObjectIDs);
}

Objek IPortableDevicePropVariantCollection menyimpan kumpulan nilai PROPVARIANT terindeks dari VARTYPE yang sama. Dalam hal ini, nilai-nilai ini berisi pengidentifikasi objek tertentu untuk setiap objek yang ditemukan pada perangkat.

Pengidentifikasi objek dan properti nama masing-masing disimpan dalam objek IPortableDeviceValuesCollection . Properti nama diatur sehingga objek pertama diberi properti nama "NewName0", objek kedua diberi properti nama "NewName1", dan sebagainya.

Kutipan berikut dari sampel menunjukkan bagaimana objek IPortableDeviceValuesCollection diinisialisasi dengan pengidentifikasi objek dan string nama baru.

HRESULT                                       hr                = S_OK;
GUID                                          guidContext       = GUID_NULL;
CSetBulkValuesCallback*                       pCallback         = NULL;
CComPtr<IPortableDeviceProperties>            pProperties;
CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
CComPtr<IPortableDeviceValues>                pObjectProperties;
CComPtr<IPortableDeviceContent>               pContent;
CComPtr<IPortableDeviceValuesCollection>      pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD                                         cObjectIDs        = 0;
if (SUCCEEDED(hr))
{
    hr = pObjectIDs->GetCount(&cObjectIDs);
    if (FAILED(hr))
    {
        printf("! Failed to get number of objectIDs from IPortableDevicePropVariantCollection, hr = 0x%lx\n", hr);
    }
}


if (SUCCEEDED(hr))
{
    for(DWORD dwIndex = 0; (dwIndex < cObjectIDs) && (hr == S_OK); dwIndex++)
    {
        CComPtr<IPortableDeviceValues>  pValues;
        PROPVARIANT                     pv = {0};

        PropVariantInit(&pv);
        hr = CoCreateInstance(CLSID_PortableDeviceValues,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_IPortableDeviceValues,
                              (VOID**) &pValues);
        if (FAILED(hr))
        {
            printf("! Failed to CoCreate CLSID_PortableDeviceValues, hr = 0x%lx\n", hr);
        }

        // Get the Object ID whose properties we will set
        if (hr == S_OK)
        {
            hr = pObjectIDs->GetAt(dwIndex, &pv);
            if (FAILED(hr))
            {
                printf("! Failed to get next Object ID from list, hr = 0x%lx\n", hr);
            }
        }

        // Save them into the IPortableDeviceValues so the driver knows which object this proeprty set belongs to
        if (hr == S_OK)
        {
            hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal);
            if (FAILED(hr))
            {
                printf("! Failed to set WPD_OBJECT_ID, hr = 0x%lx\n", hr);
            }
        }

        // Set the new values.  In this sample, we attempt to set the name property.
        if (hr == S_OK)
        {
            CAtlStringW strValue;
            strValue.Format(L"NewName%d", dwIndex);

            hr = pValues->SetStringValue(WPD_OBJECT_NAME, strValue.GetString());
            if (FAILED(hr))
            {
                printf("! Failed to set WPD_OBJECT_NAME, hr = 0x%lx\n", hr);
            }
        }

        // Add this property set to the collection
        if (hr == S_OK)
        {
            hr = pPropertiesToWrite->Add(pValues);
            if (FAILED(hr))
            {
                printf("! Failed to add values to collection, hr = 0x%lx\n", hr);
            }
        }
        PropVariantClear(&pv);
    }
}

Setelah sampel membuat objek IPortableDeviceValuesCollection yang berisi pengidentifikasi objek dan pasangan nama, ia dapat memulai operasi asinkron.

Operasi penulisan asinkron dimulai ketika sampel memanggil metode IPortableDevicePropertiesBulk::QueueSetValuesByObjectList . Metode ini memberi tahu driver bahwa operasi massal akan dimulai. Setelah ini, sampel memanggil metode IPortableDeviceBulk::Start untuk mulai benar-benar menulis nilai nama baru.

   HRESULT                                       hr                = S_OK;
   GUID                                          guidContext       = GUID_NULL;
   CSetBulkValuesCallback*                       pCallback         = NULL;
   CComPtr<IPortableDeviceProperties>            pProperties;
   CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
   CComPtr<IPortableDeviceValues>                pObjectProperties;
   CComPtr<IPortableDeviceContent>               pContent;
   CComPtr<IPortableDeviceValuesCollection>      pPropertiesToWrite;
   CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
   DWORD                                         cObjectIDs        = 0;
   if (SUCCEEDED(hr))
   {
       hr = pPropertiesBulk->QueueSetValuesByObjectList(pPropertiesToWrite,
                                                        pCallback,
                                                        &guidContext);


       if(SUCCEEDED(hr))
       {
           // Cleanup any previously created global event handles.
           if (g_hBulkPropertyOperationEvent != NULL)
           {
               CloseHandle(g_hBulkPropertyOperationEvent);
               g_hBulkPropertyOperationEvent = NULL;
           }

           // In order to create a simpler to follow example we create and wait infinitly
           // for the bulk property operation to complete and ignore any errors.
           // Production code should be written in a more robust manner.
           // Create the global event handle to wait on for the bulk operation
           // to complete.
           g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
           if (g_hBulkPropertyOperationEvent != NULL)
           {
               // Call Start() to actually being the Asynchronous bulk operation.
               hr = pPropertiesBulk->Start(guidContext);
               if(FAILED(hr))
               {
                   printf("! Failed to start property operation, hr = 0x%lx\n", hr);
               }
           }
           else
           {
               printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n");
           }
       }
       else
       {
           printf("! QueueSetValuesByObjectList Failed, hr = 0x%lx\n", hr);
       }
   }

Perhatikan bahwa sampel menunggu jangka waktu yang sangat lama agar operasi selesai. Jika ini adalah aplikasi produksi, kode perlu dimodifikasi.

Antarmuka IPortableDevice

Antarmuka IPortableDeviceContent

Antarmuka IPortableDeviceProperties

Antarmuka IPortableDevicePropertiesBulk

Antarmuka IPortableDevicePropVariantCollection

Panduan Pemrograman