0x00000010读取字符串的字符时出错.PROPVARIANT结构
0x00000010 Error reading characters of string. PROPVARIANT structure
以下是我如何使用WASAPI API相关函数获得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
结构第一眼就能正确呈现。然而,当使用VS的属性watch进行进一步检查时,所有字符串类型的属性都会返回此问题标题中反映的错误。因此,当我尝试检索我的音频端点设备的名称时,该名称包含我的PROPVARIANT
结构的pwszVal
属性,如下所示:
LPWSTR test = propVari.pwszVal;
我无法检索所需的数据。我尝试过用各种转换器方法复制字符串,但都无济于事。我知道这个错误有很多问题,但我似乎无法解决这个错误。
以下是PROPVARIANT
的文档及其相应的属性:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa380072(v=vs.85).aspx
在本文档中,它指出"PROPVARIANT
成员vt
设置为VT_LPWSTR
"VT_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
是我想要的。非常感谢您的帮助/提示。
您没有正确填充向量。您存储的是本地变量的内存地址,而不是变量引用的实际项目。
更糟糕的是,您正在使用std::vector::assign()
添加项目。CCD_ 17将矢量的全部内容替换为指定的值。如果集合中有多个设备,则最终不会得到多个设备的矢量。您应该使用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();
}
以下代码基于您的代码,但没有模糊向量,看起来运行良好。在运行过程中,我得到了"FriendlyName:扬声器/HP(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: %sn", 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编译。
我为像我一样在这个页面上好奇的人编写的代码:
您还需要这个policyconfig.h文件
#include <windows.h>
#include <ole2.h>
#include <ShellAPI.h>
#include <olectl.h>
#include <mmdeviceapi.h>
#include <propsys.h>
#include <propvarutil.h>
#include <stdio.h>
#include <Functiondiscoverykeys_devpkey.h>
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <atlstr.h>
#include <atlcore.h>
#include "Policyconfig.h"
#include "Propidl.h"
#include "Functiondiscoverykeys_devpkey.h"
#pragma comment(lib, "ole32")
#pragma comment(lib, "propsys")
using namespace std;
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
class DeviceProps {
public:
string id;
string name;
string dll;
int iconID = 0;
bool isActive = false;
};
static HRESULT getDeviceProperty(IMMDevice* pDevice, DeviceProps* output)
{
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))
{
std::wstring wstr(PropVariantToStringWithDefault(prop, L"missing"));
std::string str(wstr.begin(), wstr.end());
output->name = str.c_str();
}
else
hr = E_UNEXPECTED;
}
hr = pStore->GetValue(PKEY_DeviceClass_IconPath, &prop);
if (SUCCEEDED(hr))
{
if (IsPropVariantString(prop))
{
PCWSTR propValue = PropVariantToStringWithDefault(prop, L"missing,0");
std::wstring propW(propValue);
std::string cPropValue(propW.begin(), propW.end());
vector<string> strings;
istringstream f(cPropValue);
string s;
while (getline(f, s, ',')) {
strings.push_back(s);
}
string location = strings[0];
string id = strings[1];
output->dll = location;
output->iconID = stoi(id);
}
else
hr = E_UNEXPECTED;
}
PropVariantClear(&prop);
pStore->Release();
}
return hr;
}
std::vector<DeviceProps> EnumAudioDevices(EDataFlow deviceType = eRender)
{
std::vector<DeviceProps> output;
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))
{
IMMDevice* pActive = NULL;
pEnumerator->GetDefaultAudioEndpoint(deviceType , eMultimedia, &pActive);
DeviceProps activeDevice;
getDeviceProperty(pActive, &activeDevice);
LPWSTR aid;
pActive->GetId(&aid);
std::wstring aid2(aid);
std::string aidS(aid2.begin(), aid2.end());
activeDevice.id = aidS;
//output.push_back(activeDevice);
pActive->Release();
IMMDeviceCollection* pCollection = NULL;
hr = pEnumerator->EnumAudioEndpoints(deviceType , 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))
{
DeviceProps device;
hr = getDeviceProperty(pDevice, &device);
LPWSTR id;
pDevice->GetId(&id);
std::wstring id2(id);
std::string idS(id2.begin(), id2.end());
device.id = idS;
if (device.id == activeDevice.id)
device.isActive = true;
output.push_back(device);
pDevice->Release();
}
}
}
pCollection->Release();
}
pEnumerator->Release();
}
//CoUninitialize();
}
return output;
}
static HRESULT setDefaultDevice(string id)
{
string:wstring devID(id.begin(), id.end());
IPolicyConfigVista* pPolicyConfig;
HRESULT hr = CoCreateInstance(__uuidof(CPolicyConfigVistaClient),
NULL, CLSCTX_ALL, __uuidof(IPolicyConfigVista), (LPVOID*)&pPolicyConfig);
if (SUCCEEDED(hr))
{
hr = pPolicyConfig->SetDefaultEndpoint(devID.c_str(), eConsole);
hr = pPolicyConfig->SetDefaultEndpoint(devID.c_str(), eMultimedia);
hr = pPolicyConfig->SetDefaultEndpoint(devID.c_str(), eCommunications);
pPolicyConfig->Release();
}
return hr;
}
static int switchDefaultDevice(EDataFlow deviceType = eRender)
{
std::vector<DeviceProps> result = EnumAudioDevices(deviceType);
if (!result.empty())
{
std::string activateID("");
for (const auto& device : result)
{
if (activateID== "x") {
activateID = device.id;
break;
}
if (device.isActive) activateID= "x";
}
if (activateID == "x" || activateID == "") activateID = result[0].id;
setDefaultDevice(activateID);
return 1;
}
return 0;
}
int wmain(int argc, WCHAR* argv[])
{
std::vector<DeviceProps> result = EnumAudioDevices(eRender);
for (const auto& device : result)
{
std::cout << (device.isActive ? "ACTIVE:" : "") << "Name: " << device.name << " DLL: " << device.dll << " (#" << device.iconID << ")" << "n" << device.id << "n";
}
switchDefaultDevice(eRender);
}
- 访问者访问变体并返回不同类型时出错
- 在Linux for Windows上编译C++代码时出错
- 读取文件的最后一行并输入到链接列表时出错
- 重载操作程序时出错>>用于类中的字符串 memebr
- 调用专用模板时出错"no matching function for call to [...]"
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- LINK 尝试使用 OpenSSL evp aes 256 c++ 时出错
- 在Google Kick start中提交时出错
- 在c++中访问int到类对象的映射时出错
- 分段错误当我试图运行程序时出错
- 使用dynamic_cast和构造函数时出错
- CHECK(调用)函数在Google Colab中出错
- 用pybind11包装C++抽象类时出错
- 为x86而非x64编译时出错
- 从R调用C++函数并对其进行集成时出错
- 这个函数哪里出错了
- C++ 创建包含链表和字符串的对象的链接列表时出错
- 为重写std::exception的库生成swig接口时出错
- 导入/导出变量时出错
- 0x00000010读取字符串的字符时出错.PROPVARIANT结构