2014-10-01 119 views
0

下面是如何获得PROPVARIANT结构WASAPI API相关的功能:0x00000010读取字符串的字符时出错。 PROPVARIANT结构

//Pointer for stored audio stream 
IAudioClient *iac = NULL; 

//Endpoint device selection 
IMMDeviceEnumerator *pEnumerator = NULL; 
IMMDevice *pDevice; 
IMMDeviceCollection *pCollection = NULL; 
CoInitialize(NULL); 
hr = CoCreateInstance(
    CLSID_MMDeviceEnumerator, NULL, 
    CLSCTX_ALL, IID_IMMDeviceEnumerator, 
    (void**)&pEnumerator); 

hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection); 

//Create vector of IMMDevices 
UINT endpointCount = NULL; 
(*pCollection).GetCount(&endpointCount); 
std::vector<IMMDevice**> IMMDevicePP; //IMMDevice seems to contain all endpoint devices, so why have a collection here? 
for (UINT i = 0; i < (endpointCount); i++) 
{ 
    IMMDevice* pp = NULL; 
    (*pCollection).Item(i, &pp); 
    IMMDevicePP.assign(1, &pp); 
} 
UINT IMMDeviceCount = IMMDevicePP.size(); 

//Enumerate Properties of IMMDevices 
std::vector<IPropertyStore*> IMMDeviceProperties; 
for (int k = 0; k < IMMDeviceCount; k++) { 
    IPropertyStore* prop = NULL; 
    (**IMMDevicePP[k]).OpenPropertyStore(STGM_READ, &prop); 
    IMMDeviceProperties.assign(1, prop); 
} 
UINT PropertyStoreCount = IMMDeviceProperties.size(); 

//Find name property of device 
std::vector<PROPVARIANT*> properties; 
for (int i = 0; i < PropertyStoreCount; i++) { 
    DWORD propCount = 1; 
    HRESULT countResult = (*IMMDeviceProperties[i]).GetCount(&propCount); 
    if (countResult == S_OK) { } 
    else { 
     int x = 5; 
    } 
    for (int p = 0; p < propCount; p++) { 
     PROPERTYKEY key; 
     HRESULT keyResult = (*IMMDeviceProperties[i]).GetAt(p, &key); 
     HRESULT getAT; 
     PROPVARIANT propVari; 
     HRESULT propVariResult = (*IMMDeviceProperties[i]).GetValue(key, &propVari); 
     propVari.vt = VT_LPWSTR; 
     LPWSTR test = propVari.pwszVal; 
     //char pwszValTest; 
     //strcpy(&pwszValTest, propVari.pwszVal); 
     //WCHAR friendlyName = *propVari.pwszVal; 
     properties.assign(1, &propVari); 
    } 
} 

所有HRESULT的回归S_OK。

生成的PROPVARIANT struct乍一看正确。但是,当进一步检查VS的属性时,请注意所有字符串类型属性都会返回此问题标题中反映的错误。所以,当我试图找回它包含我PROPVARIANT结构的的pwszVal财产,像这样我的音频终端设备的名称:

LPWSTR test = propVari.pwszVal; 

我无法检索所需的数据。我试图用各种转换器方法复制字符串无济于事。我知道这个错误是在很多问题上,但我似乎无法破解这个错误。

这里的文档为PROPVARIANT及其相应的属性:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa380072(v=vs.85).aspx

在本文档中它指出“PROPVARIANT构件vt设为VT_LPWSTRVT_LPWSTR是枚举类型和对应于值31。而VT_BLOB对应于值65.我的vt成员正在设置为VT_BLOB或65而不是31或VT_LPWSTR。这是为什么?这是矛盾的,以本文档中的规定值:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd370812(v=vs.85).aspx

手动设置vt成员也不会改变/修复串读错误:

propVari.vt = VT_LPWSTR; 

PKEY_Device_FriendlyName是什么我基本上在之后任何帮助/提示,​​非常感谢。

+0

这是不可能确切知道什么错,没有看到更多的代码。在调用'GetValue'之前尝试调用'PropVariantInit',看看是否有所作为。 – 2014-10-01 19:52:26

+0

我想我发布了所有相关的东西。 PropVariantInit似乎没有帮助。 – gordlonious 2014-10-02 23:21:45

回答

1

下面的代码,根据你的,但没有混淆矢量似乎很好地工作。在奔跑中,我得到了“友好名称:扬声器/惠普(IDT高保真音频编解码器)”,这款笔记本在这里看起来很正确。

当使用COM并且没有某种智能指针时,要小心地释放所有的指针。并且总是检查所有结果。 COM调用可能因各种原因而失败。

#define WINVER _WIN32_WINNT_VISTA 
#define WIN32_LEAN_AND_MEAN 
#define UNICODE 
#define STRICT 
#include <windows.h> 
#include <ole2.h> 
#include <mmdeviceapi.h> 
#include <propsys.h> 
#include <propvarutil.h> 
#include <stdio.h> 
#include <Functiondiscoverykeys_devpkey.h> 

#pragma comment(lib, "ole32") 
#pragma comment(lib, "propsys") 

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); 
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); 

static HRESULT 
DumpDeviceProperties(IMMDevice *pDevice) 
{ 
    IPropertyStore *pStore = NULL; 
    HRESULT hr = pDevice->OpenPropertyStore(STGM_READ, &pStore); 
    if (SUCCEEDED(hr)) 
    { 
     PROPVARIANT prop; 
     PropVariantInit(&prop); 
     hr = pStore->GetValue(PKEY_Device_FriendlyName, &prop); 
     if (SUCCEEDED(hr)) 
     { 
      if (IsPropVariantString(prop)) 
       wprintf(L"FriendlyName: %s\n", PropVariantToStringWithDefault(prop, L"(missing)")); 
      else 
       hr = E_UNEXPECTED; 
     } 
     PropVariantClear(&prop); 
     pStore->Release(); 
    } 
    return hr; 
} 

int 
wmain(int argc, WCHAR *argv[]) 
{ 
    HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED); 
    if (SUCCEEDED(hr)) 
    { 
     IMMDeviceEnumerator *pEnumerator = NULL; 
     hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void **>(&pEnumerator)); 
     if (SUCCEEDED(hr)) 
     { 
      IMMDeviceCollection *pCollection = NULL; 
      hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection); 
      if (SUCCEEDED(hr)) 
      { 
       UINT cEndpoints = 0; 
       hr = pCollection->GetCount(&cEndpoints); 
       if (SUCCEEDED(hr)) 
       { 
        for (UINT n = 0; SUCCEEDED(hr) && n < cEndpoints; ++n) 
        { 
         IMMDevice *pDevice = NULL; 
         hr = pCollection->Item(n, &pDevice); 
         if (SUCCEEDED(hr)) 
         { 
          hr = DumpDeviceProperties(pDevice); 
          pDevice->Release(); 
         } 
        } 
       } 
       pCollection->Release(); 
      } 
      pEnumerator->Release(); 
     } 
     CoUninitialize(); 
    } 
    return SUCCEEDED(hr) ? 0 : 1; 
} 

编译使用:cl -nologo -MDd -Zi -W3 -Od lsdevices.cpp与MSVC 2013年

+0

这条线是帮助最'hr = pStore-> GetValue(PKEY_Device_FriendlyName,&prop);'谢谢 – gordlonious 2014-10-03 00:09:58

1

你没有正确填写你的载体。您正在存储本地变量的内存地址,而不是变量引用的实际项目。

更糟糕的是,您正在使用std::vector::assign()添加项目。 assign()用指定值替换矢量的全部内容。如果一个集合中有多个设备,则最终不会得到多个设备的矢量。您应该使用push_back()而不是assign()

你正在用你所有的载体犯这些错误。

请注意,在调用对象的方法时,应使用->运算符而不是(*).。它会使代码更清晰,更易于阅读。

试试这个:

//Endpoint device selection 
IMMDeviceEnumerator *pEnumerator = NULL; 
IMMDeviceCollection *pCollection = NULL; 

CoInitialize(NULL); 
hr = CoCreateInstance(
    CLSID_MMDeviceEnumerator, NULL, 
    CLSCTX_ALL, IID_IMMDeviceEnumerator, 
    (void**)&pEnumerator); 

hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection); 
pEnumerator->Release(); 

//Create vector of IMMDevices 
std::vector<IMMDevice*> IMMDevice; 
UINT endpointCount = 0; 
hr = pCollection->GetCount(&endpointCount); 
if (hr == S_OK) { 
    IMMDevice.reserve(endpointCount); 
    for (UINT i = 0; i < endpointCount; ++i) { 
     IMMDevice *pDevice = NULL; 
     hr = pCollection->Item(i, &pDevice); 
     if (hr == S_OK) { 
      IMMDevice.push_back(pDevice); 
     } 
    } 
} 
UINT IMMDeviceCount = IMMDevice.size(); 

pCollection->Release(); 

//Enumerate Properties of IMMDevices 
std::vector<IPropertyStore*> IMMDeviceProperties; 
IMMDeviceProperties.reserve(IMMDeviceCount); 
for (int k = 0; k < IMMDeviceCount; k++) { 
    IPropertyStore* prop = NULL; 
    hr = IMMDevice[k]->OpenPropertyStore(STGM_READ, &prop); 
    if (hr == S_OK) { 
     IMMDeviceProperties.push_back(prop); 
    } 
} 
UINT PropertyStoreCount = IMMDeviceProperties.size(); 

//Find name property of devices 
std::vector<std::wstring> MMDeviceFriendlyNames; 
MMDeviceFriendlyNames.reserve(IMMDeviceCount); 
for (int i = 0; i < PropertyStoreCount; i++) { 
    PROPVARIANT propVari; 
    PropVariantInit(&propVari); 
    hr = IMMDeviceProperties[i]->GetValue(PKEY_Device_FriendlyName, &propVari); 
    if (hr == S_OK) { 
     MMDeviceFriendlyNames.push_back(propVari.pwszVal); 
     PropVariantClear(&propVari); 
    } 
} 

// use vectors as needed... 

for (UINT i = 0; i < PropertyStoreCount; ++i) { 
    IMMDeviceProperties[i]->Release(); 
} 
for (UINT i = 0; i < IMMDeviceCount; ++i) { 
    IMMDevice[i]->Release(); 
} 
+0

感谢您的矢量建议!对C++很新颖! – gordlonious 2014-10-03 00:09:20