Windows设备:获取;地点“;UVC网络摄像头给定IMFActivate*的字符串
当转到Windows的“设备管理器”并单击(几乎)列表中的任何设备时,“常规”选项卡中的一条信息称为“位置”。这是一个字符串,它是:Windows设备:获取;地点“;UVC网络摄像头给定IMFActivate*的字符串,windows,winapi,ms-media-foundation,device-manager,uvc,Windows,Winapi,Ms Media Foundation,Device Manager,Uvc,当转到Windows的“设备管理器”并单击(几乎)列表中的任何设备时,“常规”选项卡中的一条信息称为“位置”。这是一个字符串,它是: 人类可读,如“关于NVIDIA GeForce GTX 1080” 半有用,如“位置0(内部高清音频总线)”或“PCI总线9,设备0,功能0” USB位置,如“Port#0004.Hub#0015”或“0009.0000.0000.004.000.000.000.000.000” 这些信息可以通过Windows的API获得 我要寻找的是从给定的IMFActiv
- 人类可读,如“关于NVIDIA GeForce GTX 1080”
- 半有用,如“位置0(内部高清音频总线)”或“PCI总线9,设备0,功能0”
- USB位置,如“Port#0004.Hub#0015”或“0009.0000.0000.004.000.000.000.000.000”
IMFActivate
对象获取信息
有没有办法做到这一点?我找不到如何从激活对象获取“设备”信息。我唯一拥有的数据是它的“符号链接”(在我的例子中,这个字符串:\?\usb\vid\u 04b4&pid\u 8888&mi\u 00#9&4fe28be&0&0000{e5323777-f976-4f5b-9b55-b94699c46e44}\global
),但该链接的格式与我在“位置”中看到的字符串完全不同
因此,我的问题是:给定设备的IMFActivate
对象,如何获取设备的“位置”字符串
更新
下面是我用来“转换”符号链接的代码,该链接由IMFActivate
提供,它是一个设备id字符串,可由设置api函数识别,然后提取“位置字符串”:
更新2
以下是在“声音、视频和游戏控制器”下的devmgmt.msc
中看到的3个音频输入设备:
- 中景生活影院(TM),位置:0000.0014.0000.013.003.000.000.000.000.000(符号链接:
)\?\SWD\MMDEVAPI{0.0.1.00000000}.{751fe058-cef2-4d28-bbeb-e438981938d7}{2eef81be-33fa-4800-9670-1cd474972c3f}
- MS LifeCam Studio(TM),位置:0000.0014.0000.013.004.004.000.000.000(符号链接:
)\?\SWD\MMDEVAPI{0.0.1.00000000}.{59267d2e-940b-45f5-8655-45372787bd85}{2eef81be-33fa-4800-9670-1cd474972c3f}
- SUB2r USB 3.0高清网络摄像头,位置:0009.0000.0000.004.000.000.000.000.000.000(符号链接:
)\?\SWD\MMDEVAPI{0.0.1.00000000}.{26a4f608-cbd8-4206-b958-d57ee6847153}{2eef81be-33fa-4800-9670-1CD47972C3F}
MFEnumDeviceSources
时列出,但它们的“符号链接”不解析为硬件设备。使用MF\u DEVSOURCE\u ATTRIBUTE\u SOURCE\u TYPE\u VIDCAP\u SYMBOLIC\u LINK
或MF\u DEVSOURCE\u ATTRIBUTE\u SOURCE\u TYPE\u AUDCAP\u SYMBOLIC\u LINK
返回的字符串这是我们可以用作输入的设备接口字符串。要获取位置信息(如果存在),需要执行3个步骤:
CONFIGRET PrintLocation(PCWSTR pszDeviceInterface)
{
ULONG cb = 0, rcb = 64;
static volatile UCHAR guz;
PVOID stack = alloca(guz);
DEVPROPTYPE PropertyType;
CONFIGRET err;
union {
PVOID pv;
PWSTR sz;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
if (!(err = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0)))
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("InstanceId=%S\n", sz);
DEVINST dnDevInst;
if (!(err = CM_Locate_DevNodeW(&dnDevInst, sz, CM_LOCATE_DEVNODE_NORMAL)))
{
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
if (!(err = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_LocationInfo, &PropertyType, pb, &rcb, 0)))
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("Location=%S\n", sz);
}
else
{
err = CR_WRONG_TYPE;
}
}
} while (err == CR_BUFFER_SMALL);
}
}
else
{
err = CR_WRONG_TYPE;
}
break;
}
} while (err == CR_BUFFER_SMALL);
return err;
}
对于IMFActivate
,我们可以使用下一个代码:
void mftest()
{
IMFAttributes *pAttributes;
if (SUCCEEDED(MFCreateAttributes(&pAttributes, 1)))
{
UINT32 count, cchLength;
IMFActivate **ppDevices, *pDevice;
if (SUCCEEDED(pAttributes->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)) &&
SUCCEEDED(MFEnumDeviceSources(pAttributes, &ppDevices, &count)) &&
count)
{
PVOID pv = ppDevices;
do
{
pDevice = *ppDevices++;
PWSTR pszDeviceInterface;
if (SUCCEEDED(pDevice->GetAllocatedString(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &pszDeviceInterface, &cchLength)))
{
DbgPrint("%S\n", pszDeviceInterface);
PrintLocation(pszDeviceInterface);
CoTaskMemFree(pszDeviceInterface);
}
} while (--count);
CoTaskMemFree(pv);
}
pAttributes->Release();
}
}
如果您有符号链接(sz)-调用
CM\u Locate\u DEVNODE(&dnevinst,sz,CM\u Locate\u DEVNODE\u NORMAL)
,然后调用CM\u Get\u DEVNODE\u PropertyW(dnevinst,&devkey\u Device\u LocationInfo,&PropertyType,pb,&rcb,0)
,您得到了位置调用CM\u Locate\u Locate\u DEVNODE()
返回CR\u无效的设备ID
。我想,IMFActivation
对象提供的“符号链接”不是安装api所期望的:((请参阅我的原始帖子,了解该链接的示例)是的,我错了。这里确实需要设备id,在您的情况下,它将是usb\vid_04b4&pid_8888&mi_00\9&4fe28be&0&0000
我确切知道内部(未记录)规则如何从设备id(append\\?\、convert\ to#、append class guid)生成符号链接,在您的情况下,这是{e5323777-f976-4f5b-9b55-b94699c46e44}
(静态\u KSCATEGORY\u VIDEO\u CAMERA),但如何以文档化的方式实现这一点不确定找到正确的方式-需要先调用CM\u获取设备接口\u属性(pszDeviceInterface,&DEVPKEY\u Device\u InstanceId
,带有IMFAttributes::Get[Allocated]string
返回的字符串,然后已经在callCM\u Locate\u DevNode
CM\u Get\u DevNode\u属性中使用返回的设备id,我找不到“location”的最大长度是MAX\u PATH
或1024
或其他什么。它“感觉”像MAX\u PATH
应该是它,但我不能确认这一点。@YePhIcK-我通常不喜欢硬编码缓冲区大小,而是在循环中动态分配它-从一些合理的大小开始,如果CR\u buffer\u SMALL
分配额外的空间-像PrintLocation
那样,该方法对视频捕获设备非常有效。失败(CM\u Get\u DevNode\u PropertyW()
返回CR\u NO\u这样的值
)用于音频捕获设备。只是做个笔记here@YePhIcK-是的,对于音频,不返回位置。但这不是错误。不是每个设备都有位置信息。这取决于每个具体设备-有些有,有些没有。查看devmgmt.msc
-您得到了相同的结果。并且一些属性对接口有意义(CM\u Get\u Device\u Interface\u PropertyW
)和一些仅用于设备实例的(CM\u Get\u DevNode\u PropertyW
)-请注意,同一个设备实例可以有多个接口。因为此位置仅存在于devnode中,而不存在于interface中。还可以尝试查找devpkey.h
中定义的其他键。例如,您可以将devpkey\u device\u LocationInfo
更改为devpkey\u device\u FriendlyName
query.i forMF\u DEVSOURCE\ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK
gotmicroscope(高清音频设备)
Device id isSWD\MMDEVAPI\{0.0.1.00000000}.{6630cade-5c94-4e5f-8a6e-ee02877a4f3f}
CONFIGRET PrintLocationSimp(PCWSTR pszDeviceInterface)
{
WCHAR buf[1024];
DEVPROPTYPE PropertyType;
ULONG BufferSize = sizeof(buf);
CONFIGRET err;
if (!(err = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, (PBYTE)buf, &BufferSize, 0)))
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("InstanceId=%S\n", buf);
DEVINST dnDevInst;
if (!(err = CM_Locate_DevNodeW(&dnDevInst, buf, CM_LOCATE_DEVNODE_NORMAL)))
{
BufferSize = sizeof(buf);
if (!(err = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_LocationInfo, &PropertyType, (PBYTE)buf, &BufferSize, 0)))
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("Location=%S\n", buf);
}
else
{
err = CR_WRONG_TYPE;
}
}
}
}
else
{
err = CR_WRONG_TYPE;
}
}
return err;
}
void mftest()
{
IMFAttributes *pAttributes;
if (SUCCEEDED(MFCreateAttributes(&pAttributes, 1)))
{
UINT32 count, cchLength;
IMFActivate **ppDevices, *pDevice;
if (SUCCEEDED(pAttributes->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)) &&
SUCCEEDED(MFEnumDeviceSources(pAttributes, &ppDevices, &count)) &&
count)
{
PVOID pv = ppDevices;
do
{
pDevice = *ppDevices++;
PWSTR pszDeviceInterface;
if (SUCCEEDED(pDevice->GetAllocatedString(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &pszDeviceInterface, &cchLength)))
{
DbgPrint("%S\n", pszDeviceInterface);
PrintLocation(pszDeviceInterface);
CoTaskMemFree(pszDeviceInterface);
}
} while (--count);
CoTaskMemFree(pv);
}
pAttributes->Release();
}
}