1

私は COM と smartpointers を初めて使用します。メモリ管理の煩わしさを避けるために、プロジェクトを生のポインターから CComPtr に変換しようとしています。一般に、関数とスコープに関して CComPointers を適切に使用する方法についてのアドバイスを探しています。私のコードのサンプル。

int  DisplayDeviceInformation(IEnumMoniker * pEnum, IMoniker * pMoniker)
{
    CComPtr<IPropertyBag> pPropBag = NULL;

    while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
    {

        HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
        if (FAILED(hr))
        {

        } 

        VARIANT var;
        VariantInit(&var);

        // Get description or friendly name.
        hr = pPropBag->Read(L"Description", &var, 0);
        if (FAILED(hr))
        {
            hr = pPropBag->Read(L"FriendlyName", &var, 0);
        }
        if (SUCCEEDED(hr))
        {
            printf("%S\n", var.bstrVal);
            VariantClear(&var); 
        }

        hr = pPropBag->Write(L"FriendlyName", &var);

        // WaveInID applies only to audio capture devices.
        hr = pPropBag->Read(L"WaveInID", &var, 0);
        if (SUCCEEDED(hr))
        {
            printf("WaveIn ID: %d\n", var.lVal);
            VariantClear(&var); 
        }

        hr = pPropBag->Read(L"DevicePath", &var, 0);
        if (SUCCEEDED(hr))
        {
            // The device path is not intended for display.
            printf("Device path: %S\n", var.bstrVal);
            VariantClear(&var); 
        }

    }
    return 0;
}

CComPtr<IMoniker> pMoniker = NULL;  
CComPtr<IMoniker> pMoniker2 = NULL;
    CComPtr<IEnumMoniker> pEnum = NULL;

    hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
//pEnum->Next(1, &pMoniker,&cFetched);

    if (SUCCEEDED(hr))
    {
        DisplayDeviceInformation(pEnum, pMoniker);     
    }
    pEnum = NULL;
    hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnum);
    //pEnum->Next(1, &pMoniker2,&cFetched);
    if (SUCCEEDED(hr))
    {
        DisplayDeviceInformation(pEnum, pMoniker);
    }

基本的に、最初の例でDisplayDeviceInformation(pEnum, pMoniker);は ap==0 エラーが発生します。ただし、コメントを外すと、pEnum->Next(1, &pMoniker,&cFetched);機能します。生のポインターを使用すると、コードが次のデバイスにスキップするだけなので、その必要はありません。アドバイスや助けがあれば、私は非常に感謝しています。事前に感謝します!

4

1 に答える 1

1

どこCComPtrでアサートが失敗するか、生のポインターにも問題がある可能性があります。事前に警告されていないだけで、参照リークなどの問題が後で発生します。

  1. IMonikerグローバルスコープでは必要ないようです
  2. IMoniker列挙子に渡す前にポインタをクリアする必要があります

下記参照:

int DisplayDeviceInformation(IEnumMoniker* pEnum, IMoniker** ppSelectedMoniker)
{
    CComPtr<IMoniker> pMoniker;
    while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
    {
        CComPtr<IPropertyBag> pPropBag; // You need it clear to start from for every moniker
        HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
        // ...
        if(we should stop enumeration and we are good with current moniker)
        {
            //ATLASSERT(ppSelectedMoniker != NULL);
            *ppSelectedMoniker = pMoniker.Detach();
            return ...
        }
        // ...
        pMoniker.Release(); // You have to do this, so that next Next would accept empty CComPtr as an argument
    }
    return 0;
}

CComPtr<IEnumMoniker> pEnumVideoMoniker;
CComPtr<IMoniker> pSelectedVideoMoniker;
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnumVideoMoniker);
if (SUCCEEDED(hr))
    DisplayDeviceInformation(pEnumVideoMoniker, &pSelectedVideoMoniker);     
CComPtr<IEnumMoniker> pEnumAudioMoniker;
CComPtr<IMoniker> pSelectedAudioMoniker;
hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnumAudioMoniker);
if (SUCCEEDED(hr))
    DisplayDeviceInformation(pEnumAudioMoniker, &pSelectedAudioMoniker);
于 2012-07-02T13:31:52.780 に答える