zoukankan      html  css  js  c++  java
  • C#调用EnumDevice获取设备信息

    本文接上篇文章 C#获取设备(Audio和Video)名称 简单整理,对第四种方式使用整理.

    EnumDevice.dll是网上下载的,也下载了对应的源代码,

    对应dll:https://download.csdn.net/download/QQ81867376/12322158

    该dll的源码: https://download.csdn.net/download/QQ81867376/12322152

    由于项目刚好是x86,所以直接使用上面下载的dll,暂未去编译源代码。

    C# 调用EnumDevice.dll的方法时候遇到不少问题,在此记录下。

    查看C++函数信息,可以使用工具dllExportViewer

    下载地址:http://www.nirsoft.net/utils/dll_export_viewer.html

    该dll的原型

    __declspec(dllimport)EnumDevice(CAPTURE_DEVICE_TYPE type, char * deviceList[], int nListLen, int & iNumCapDevices);

    由于未在前面添加extern "C" 一直找不到该方法,暂时使用了索引来进行。

    如果函数过多且经常变化使用索引不恰当 ,但这里只有一个方法,因此无碍,就直接使用索引。

    C#方法声明 这里耽误点时间,开始仅仅以为按照类型对上即可,定义了如下方法:

              //LPStr、LPWStr、BStr 或 LPTStr  
            [DllImport(EnumDeviceDll, EntryPoint = "#1", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
            public extern static int EnumDevice(CAPTURE_DEVICE_TYPE type,
               [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] deviceList,
               int nListLen, ref int iNumCapDevices);
    
    public static List<string> GetDeviceList()
            {
                var list = new string[10];
                int index = 0;           
                int result = EnumDevice(CAPTURE_DEVICE_TYPE.DSHOW_AUDIO_DEVICE, list, list.Length, ref index);
                List<string> listAudio = null;
                if (result == 0)
                {
                    listAudio = new List<string>();
    
                    foreach (var item in list)
                    {
                        if (string.IsNullOrEmpty(item))
                        {
                            continue;
                        }
                        listAudio.Add(item);
                    }
                }
                return listAudio;
            }

    一运行就报错:其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏 .

    无奈 就查看源代码,发现每一项没有指定大小.就添加了代码

      for (int i = 0; i < list.Length; i++)
                {
                    list[i] = new string(new char[256]);
                }

    运行果然没有报错,

    可是有乱码和用ffmpeg调用指令 (ffmpeg -list_devices true -f dshow -i dummy) 输出的结果一样乱码.

    于是各种转码无效, 各种定义函数 CharSet = CharSet.Ansi,

    ArraySubType = UnmanagedType.LPStr //LPStr、LPWStr、BStr 或 LPTStr 。

    试了个遍全都无效,无奈只能换思路了。

    修改对应类型,C++里面的 char*,正常直接可以用C#里面string或者char *,

    之前使用C#调用FFMpeg的API播放rtmp协议的视频和语音的时候 好像使用过,看了下之前代码,重新定义了接口

      [DllImport(EnumDeviceDll, EntryPoint = "#1", CallingConvention = CallingConvention.Cdecl)]
            public extern static int EnumDevice(CAPTURE_DEVICE_TYPE type,
                 [In, Out, MarshalAs(UnmanagedType.LPArray)]  IntPtr[] deviceList,
               int nListLen, ref int iNumCapDevices);

    调用赋值

       var list = new IntPtr[10];
                int index = 0;
             for (int i = 0; i < list.Length; i++)
                {
                  list[i] = Marshal.AllocHGlobal(256);
                  }
    

    直接给每一项分配内存,Marshal.AllocHGlobal(256)

    结果是 无法或者到底有多个设备列表, 除了正常外 其他全是乱码,

    后来就用字符串来代替,

    var stringEmpty = new string(new char[256]);

    list[i] = Marshal.StringToHGlobalAnsi(stringEmpty);

    终于一切都正常了,C#调用一个vc++的函数,就耽误个把小时。           

  • 相关阅读:
    Rainmeter 雨滴桌面 主题分享
    行人检測之HOG特征(Histograms of Oriented Gradients)
    const和readonly差别
    ADB命令解析
    Java实现 蓝桥杯VIP 算法训练 接水问题
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
  • 原文地址:https://www.cnblogs.com/hubEnergy/p/12681558.html
Copyright © 2011-2022 走看看