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++的函數,就耽誤個把小時。           


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM