这篇文章主要讲解了“C#如何使用com获取Windows摄像头列表”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#如何使用com获取Windows摄像头列表”吧!
我们使用directshow获取视频设备列表,由于com的跨语言特性,完全可以直接在C#中调用,而不用通过C++封装一层dll给C#使用。我们首先定义需要的com对象接口。
static readonly Guid SystemDeviceEnum = new Guid(0x62BE5D10, 0x60EB, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
static readonly Guid VideoInputDevice = new Guid(0x860BB310, 0x5D01, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
[Flags]
enum CDef
{
None = 0x0,
ClassDefault = 0x1,
BypassClassManager = 0x2,
ClassLegacy = 0x4,
MeritAboveDoNotUse = 0x8,
DevmonCMGRDevice = 0x10,
DevmonDMO = 0x20,
DevmonPNPDevice = 0x40,
DevmonFilter = 0x80,
DevmonSelectiveMask = 0xF0
}
[ComImport]
[SuppressUnmanagedCodeSecurity]
[Guid("3127CA40-446E-11CE-8135-00AA004BB851")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IErrorLog
{
[PreserveSig]
int AddError([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In] System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo);
}
[ComImport]
[Localizable(false)]
[SuppressUnmanagedCodeSecurity]
[Guid("55272A00-42CB-11CE-8135-00AA004BB851")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPropertyBag
{
[PreserveSig]
int Read([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [MarshalAs(UnmanagedType.Struct)] out object pVar, [In] IErrorLog pErrorLog);
[PreserveSig]
int Write([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In][MarshalAs(UnmanagedType.Struct)] ref object pVar);
}
[ComImport]
[SuppressUnmanagedCodeSecurity]
[Guid("29840822-5B84-11D0-BD3B-00A0C911CE86")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ICreateDevEnum
{
[PreserveSig]
int CreateClassEnumerator([In][MarshalAs(UnmanagedType.LPStruct)] Guid pType, out IEnumMoniker ppEnumMoniker, [In] CDef dwFlags);
}
与directshow流程一样,调用com枚举设备即可,本文只展示获取设备名称(FriendlyName),获取其他属性可以参照c++调用directshow的实现。
/// <summary>
/// 枚举视频设备
/// </summary>
public static IEnumerable<string> Devices
{
get
{
IMoniker[] monikers = new IMoniker[5];
var devEnum = Activator.CreateInstance(Type.GetTypeFromCLSID(SystemDeviceEnum)) as ICreateDevEnum;
IEnumMoniker moniker;
if (devEnum.CreateClassEnumerator(VideoInputDevice, out moniker, 0) == 0)
{
while (true)
{
int r = moniker.Next(1, monikers, IntPtr.Zero);
if (r != 0 || monikers[0] == null)
break;
yield return GetName(monikers[0]);
foreach (var i in monikers)
{
if(i!=null)
Marshal.ReleaseComObject(i);
}
}
Marshal.ReleaseComObject(moniker);
}
Marshal.ReleaseComObject(devEnum);
}
}
/// <summary>
/// 获取设备名称
/// </summary>
/// <param name="moniker"></param>
/// <returns></returns>
static string GetName(IMoniker moniker)
{
IPropertyBag property;
object value;
object temp = null;
try
{
Guid guid = typeof(IPropertyBag).GUID;
moniker.BindToStorage(null, null, ref guid, out temp);
property = temp as IPropertyBag;
int hr = property.Read("FriendlyName", out value, null);
Marshal.ThrowExceptionForHR(hr);
return value as string;
}
catch (Exception)
{
return null;
}
finally
{
if (temp != null)
{
Marshal.ReleaseComObject(temp);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
namespace AC
{
public class EnumDevices
{
/// <summary>
/// 枚举视频设备
/// </summary>
public static IEnumerable<string> Devices
{
get
{
IMoniker[] monikers = new IMoniker[5];
var devEnum = Activator.CreateInstance(Type.GetTypeFromCLSID(SystemDeviceEnum)) as ICreateDevEnum;
IEnumMoniker moniker;
if (devEnum.CreateClassEnumerator(VideoInputDevice, out moniker, 0) == 0)
{
while (true)
{
int hr = moniker.Next(1, monikers, IntPtr.Zero);
if (hr != 0 || monikers[0] == null)
break;
yield return GetName(monikers[0]);
foreach (var i in monikers)
{
if(i!=null)
Marshal.ReleaseComObject(i);
}
}
Marshal.ReleaseComObject(moniker);
}
Marshal.ReleaseComObject(devEnum);
}
}
/// <summary>
/// 获取设备名称
/// </summary>
/// <param name="moniker"></param>
/// <returns></returns>
static string GetName(IMoniker moniker)
{
IPropertyBag property;
object value;
object temp = null;
try
{
Guid guid = typeof(IPropertyBag).GUID;
moniker.BindToStorage(null, null, ref guid, out temp);
property = temp as IPropertyBag;
int hr = property.Read("FriendlyName", out value, null);
Marshal.ThrowExceptionForHR(hr);
return value as string;
}
catch (Exception)
{
return null;
}
finally
{
if (temp != null)
{
Marshal.ReleaseComObject(temp);
}
}
}
static readonly Guid SystemDeviceEnum = new Guid(0x62BE5D10, 0x60EB, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
static readonly Guid VideoInputDevice = new Guid(0x860BB310, 0x5D01, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
[Flags]
enum CDef
{
None = 0x0,
ClassDefault = 0x1,
BypassClassManager = 0x2,
ClassLegacy = 0x4,
MeritAboveDoNotUse = 0x8,
DevmonCMGRDevice = 0x10,
DevmonDMO = 0x20,
DevmonPNPDevice = 0x40,
DevmonFilter = 0x80,
DevmonSelectiveMask = 0xF0
}
[ComImport]
[SuppressUnmanagedCodeSecurity]
[Guid("3127CA40-446E-11CE-8135-00AA004BB851")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IErrorLog
{
[PreserveSig]
int AddError([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In] System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo);
}
[ComImport]
[Localizable(false)]
[SuppressUnmanagedCodeSecurity]
[Guid("55272A00-42CB-11CE-8135-00AA004BB851")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPropertyBag
{
[PreserveSig]
int Read([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [MarshalAs(UnmanagedType.Struct)] out object pVar, [In] IErrorLog pErrorLog);
[PreserveSig]
int Write([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In][MarshalAs(UnmanagedType.Struct)] ref object pVar);
}
[ComImport]
[SuppressUnmanagedCodeSecurity]
[Guid("29840822-5B84-11D0-BD3B-00A0C911CE86")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ICreateDevEnum
{
[PreserveSig]
int CreateClassEnumerator([In][MarshalAs(UnmanagedType.LPStruct)] Guid pType, out IEnumMoniker ppEnumMoniker, [In] CDef dwFlags);
}
}
}
.net 6.0代码示例如下
// See https://aka.ms/new-console-template for more information
using AC;
//枚举设备
foreach (var i in EnumDevices.Devices)
{
//打印设备名称
Console.WriteLine(i);
}
效果:
感谢各位的阅读,以上就是“C#如何使用com获取Windows摄像头列表”的内容了,经过本文的学习后,相信大家对C#如何使用com获取Windows摄像头列表这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。