Определить, подключены ли наушники или нет через С#

Нет примера, как определить, подключены ли наушники через C#.

Я предполагаю, что для этого должно быть какое-то событие...

Имеет ли смысл использовать WMI?

 ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2",
                                                                  "SELECT * FROM Win32_SoundDevice");

foreach (ManagementObject queryObj in searcher.Get())
{
    Console.WriteLine("-----------------------------------");
    Console.WriteLine("Win32_SoundDevice instance");
    Console.WriteLine("-----------------------------------");
    Console.WriteLine("StatusInfo: {0}", queryObj["StatusInfo"]);
}

Кто-нибудь был бы так рад предоставить его?

Благодарю вас!


person DmitryBoyko    schedule 23.11.2015    source источник
comment
@MicrosoftDN Я не вижу исходного кода на C#. Извините, это не помогает. Мне нужен пример кода, пожалуйста.   -  person DmitryBoyko    schedule 23.11.2015
comment
@Dimi Я дал ответ, который, надеюсь, поможет вам ;-)   -  person Markus Safar    schedule 26.11.2015


Ответы (3)


Обнаружение изменений такого рода возможно с помощью IMMDeviceEnumerator::RegisterEndpointNotificationCallback.

Поскольку вы хотите справиться с этим на C#, вам понадобится управляемая оболочка, которую уже реализовал Akos Mattiassich. Подробный пример можно найти здесь: Управляемая оболочка вокруг MMAudioDeviceApi

Он утверждает:

Программа может воспроизводить тестовый звук на выбранных устройствах и автоматически обновлять список при изменениях, например. через панель управления или при физическом подключении нового устройства.

person Markus Safar    schedule 26.11.2015
comment
Ты победитель, бро! Благодарю вас! - person DmitryBoyko; 26.11.2015
comment
Пример (суть) кода был бы полезен, поскольку ссылка может (будет?) в конечном итоге исчезнуть. - person ivan_pozdeev; 01.12.2015

Я бы не рекомендовал использовать API COM+ самостоятельно.

Взгляните на пакет NAudio NuGet:

Install-Package NAudio

Вы должны быть в состоянии перечислить аудиоустройства с их подключенными/отключенными состояниями следующим образом:

var enumerator = new NAudio.CoreAudioApi.MMDeviceEnumerator();

// Allows you to enumerate rendering devices in certain states
var endpoints = enumerator.EnumerateAudioEndPoints(
    DataFlow.Render,
    DeviceState.Unplugged | DeviceState.Active);
foreach (var endpoint in endpoints)
{
    Console.WriteLine("{0} - {1}", endpoint.DeviceFriendlyName, endpoint.State);
}

// Aswell as hook to the actual event
enumerator.RegisterEndpointNotificationCallback(new NotificationClient());

Где NotificationClient реализован следующим образом:

class NotificationClient : NAudio.CoreAudioApi.Interfaces.IMMNotificationClient
{
    void IMMNotificationClient.OnDeviceStateChanged(string deviceId, DeviceState newState)
    {
        Console.WriteLine("OnDeviceStateChanged\n Device Id -->{0} : Device State {1}", deviceId, newState);
    }

    void IMMNotificationClient.OnDeviceAdded(string pwstrDeviceId) { }
    void IMMNotificationClient.OnDeviceRemoved(string deviceId) { }
    void IMMNotificationClient.OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId) { }
    void IMMNotificationClient.OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key) { }
}

Должен дать результат, аналогичный:

введите описание изображения здесь

Я думаю, что причина, по которой он дважды обнаруживает подключение/отключение на приведенном выше снимке экрана, заключается в том, что на Macbook они используют один разъем для микрофона и наушников.

person Yannick Motton    schedule 26.11.2015
comment
Благодарю вас! Я проверил первый. Но твой ответ тоже хорош. - person DmitryBoyko; 26.11.2015
comment
Np, вы хотели обнаружить фактическое событие или перечислить состояния? Поскольку NAudio также освещает это событие. - person Yannick Motton; 26.11.2015
comment
На самом деле они оба. И событие чрезвычайно важно, потому что мне нужно обеспечить функцию преобразования текста в речь, когда наушники подключены. Спасибо, чувак! - person DmitryBoyko; 26.11.2015
comment
Круто, немного расширил образец. Должно работать из коробки. - person Yannick Motton; 26.11.2015
comment
Привет! Я столкнулся с другой проблемой там. Как-то невозможно разницы, в каком аудиоустройстве встроенный звук, а в каком наушники. Я имею в виду, что они имеют одинаковое имя, и только если мы подключаем наушники, они переходят в активное состояние. Представьте, если я запускаю приложение с подключенными наушниками, как я узнаю, является ли текущее устройство наушниками, а не встроенным звуком в ПК? - person DmitryBoyko; 01.12.2015
comment
@Dimi: зачем тебе вообще нужно знать, подключены ли наушники и когда? С тем же успехом я могу подключить внешние динамики к аудиовыходу... - person Yannick Motton; 01.12.2015
comment
Я согласен. Но мне нужно включить какую-то особую логику при подключении наушников и наоборот. - person DmitryBoyko; 01.12.2015
comment
Не уверен, что Windows API знает, является ли устройство внутренним/внешним. Таким образом, вы хотите обеспечить преобразование текста в речь только в том случае, если что-то подключено к разъему аудиовыхода, что может быть даже не наушниками. Пользователь никогда не захочет этого со встроенными динамиками? Как насчет кнопки, позволяющей ему выбирать? - person Yannick Motton; 01.12.2015
comment
Да... У меня есть приложение, у которого вообще нет графического интерфейса. Так что никаких кнопок... Но мне нравится ваше определение внутреннего/внешнего аудиоустройства. Попробую поискать в этой теме. Спасибо за помощь, бро! - person DmitryBoyko; 01.12.2015
comment
Эй, Янник! Я нашел способ сделать то, что мне нужно. Мне нужно получить информацию о разъеме аудиоустройства. MS Windows показывает это как LR Front Panel 3,5 mm Jack . Вы знаете, как получить эту информацию через NAudio? - person DmitryBoyko; 01.12.2015
comment
Привет, кто-нибудь нашел решение для подключения / отключения разъема для наушников, мне нужно запустить логику, основанную на подключении / отключении разъема для наушников, также для меня приведенный выше код не запускается, когда я подключаю разъем для наушников, все мое приложение Windows аварийно завершает работу. - person Alaa Abuzaghleh; 14.05.2020

Ниже приведен (минимальный) пример приложения Windows Forms на основе IMMNotificationClient интерфейс, который не требует сторонних библиотек.

Вы будете получать уведомление всякий раз, когда мультимедийное устройство будет подключено/отключено. Затем вы можете просмотреть свойства устройства и предпринять соответствующие действия. Вы также можете перечислить существующие устройства и проверить, подключены ли наушники (см. свойство IsConnected).

Создание COM-взаимодействия

Обратите внимание, что пример кода включает определение соответствующего COM-объекта. В производственной среде я бы, вероятно, создал сборку COM-взаимодействия для базовой mmdevapi.dll. Вы можете сделать это, сначала создав библиотеку типов из файлов заголовков (необходимо установить Windows SDK):

midl /out c:\tmp /header "C:\Program Files (x86)\Windows Kits\8.1\Include\um\mmdeviceapi.h" "C:\Program Files (x86)\Windows Kits\8.1\Include\um\mmdeviceapi.idl"

Затем вам нужно сгенерировать сборку взаимодействия из библиотеки типов, используя tlbimp.exe:

tlbimp /out:MMDevAPI.Interop.dll mmdeviceapi.tlb

Образец прослушивателя MultiMediaNotificationListener

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

namespace MultiMediaNotificationListenerSample
{
    class MainWindow : Form
    {
        [STAThread]
        private static void Main(string[] args)
        {
            using (var notificationClient = new MultiMediaNotificationListener())
            {
                Trace.WriteLine(string.Format("Headphone is {0}connected", notificationClient.IsConnected ? "": "not "));
                Application.Run(new MainWindow());
            }
        }
    }

    class MultiMediaNotificationListener : IMMNotificationClient, IDisposable
    {
        private readonly IMMDeviceEnumerator _deviceEnumerator;

        public MultiMediaNotificationListener()
        {
            if (Environment.OSVersion.Version.Major < 6)
            {
                throw new NotSupportedException("This functionality is only supported on Windows Vista or newer.");
            }
            _deviceEnumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator();
            _deviceEnumerator.RegisterEndpointNotificationCallback(this);
        }

        ~MultiMediaNotificationListener()
        {
            Dispose(false);
        }

        public bool IsConnected
        {
            get
            {
                IMMDeviceCollection deviceCollection;
                _deviceEnumerator.EnumAudioEndpoints(EDataFlow.eRender, (uint)DeviceState.DEVICE_STATE_ACTIVE, out deviceCollection);

                uint deviceCount = 0;
                deviceCollection.GetCount(out deviceCount);
                for (uint i = 0; i < deviceCount; i++)
                {
                    IMMDevice device;
                    deviceCollection.Item(i, out device);

                    IPropertyStore propertyStore;
                    device.OpenPropertyStore((uint)STGM.STGM_READ, out propertyStore);

                    PROPVARIANT property;
                    propertyStore.GetValue(ref PropertyKey.PKEY_Device_DeviceDesc, out property);

                    var value = (string)property.Value;
                    Marshal.ReleaseComObject(propertyStore);
                    Marshal.ReleaseComObject(device);

                    if (value == "Headphones")
                    {
                        return true;
                    }
                }

                Marshal.ReleaseComObject(deviceCollection);
                return false;
            }
        }

        public void OnDefaultDeviceChanged(EDataFlow dataFlow, ERole deviceRole, string pwstrDefaultDeviceId)
        {
        }

        public void OnDeviceStateChanged(string pwstrDeviceId, uint dwNewState)
        {
            IMMDevice device;
            _deviceEnumerator.GetDevice(pwstrDeviceId, out device);

            IPropertyStore propertyStore;
            device.OpenPropertyStore((uint)STGM.STGM_READ, out propertyStore);

            Trace.WriteLine(string.Format("OnDeviceStateChanged:\n  Device Id {0}\tDevice State {1}", pwstrDeviceId, (DeviceState)dwNewState));

            var properties = PropertyKey.GetPropertyKeys()
                .Select(
                propertyKey =>
                {
                    PROPVARIANT property;
                    propertyStore.GetValue(ref propertyKey, out property);
                    return new { Key = PropertyKey.GetKeyName(propertyKey), Value = property.Value };
                })
                .Where(@t => @t.Value != null);

            foreach (var property in properties)
            {
                Trace.WriteLine(string.Format("    {0}\t{1}", property.Key, property.Value));
            }

            Marshal.ReleaseComObject(propertyStore);
            Marshal.ReleaseComObject(device);
        }

        public void OnDeviceAdded(string deviceId)
        {
        }

        public void OnDeviceRemoved(string deviceId)
        {
        }

        public void OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key)
        {
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            _deviceEnumerator.UnregisterEndpointNotificationCallback(this);
            Marshal.ReleaseComObject(_deviceEnumerator);
        }
    }

    public enum STGM : uint
    {
        STGM_READ = 0x0,
        STGM_WRITE = 0x1,
        STGM_READWRITE = 0x2
    }

    public enum DeviceState
    {
        DEVICE_STATE_ACTIVE = 0x00000001,
        DEVICE_STATE_DISABLED = 0x00000002,
        DEVICE_STATE_NOTPRESENT = 0x00000004,
        DEVICE_STATE_UNPLUGGED = 0x00000008,
        DEVICE_STATEMASK_ALL = 0x0000000f
    }

    [ComImport]
    [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
    internal class MMDeviceEnumerator
    {
    }

    public enum EDataFlow
    {
        eRender,
        eCapture,
        eAll,
        EDataFlow_enum_count
    }

    public enum ERole
    {
        eConsole,
        eMultimedia,
        eCommunications,
        ERole_enum_count
    }

    [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMDeviceCollection
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetCount(out uint pcDevices);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void Item([In] uint nDevice, [MarshalAs(UnmanagedType.Interface)] out IMMDevice ppDevice);
    }

    [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMDeviceEnumerator
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void EnumAudioEndpoints([ComAliasName("MMDevAPI.Interop.EDataFlow")] [In] EDataFlow dataFlow, [In] uint dwStateMask, [MarshalAs(UnmanagedType.Interface)] out IMMDeviceCollection ppDevices);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetDefaultAudioEndpoint([ComAliasName("MMDevAPI.Interop.EDataFlow")] [In] EDataFlow dataFlow, [ComAliasName("MMDevAPI.Interop.ERole")] [In] ERole role, [MarshalAs(UnmanagedType.Interface)] out IMMDevice ppEndpoint);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetDevice([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrId, [MarshalAs(UnmanagedType.Interface)] out IMMDevice ppDevice);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void RegisterEndpointNotificationCallback([MarshalAs(UnmanagedType.Interface)] [In] IMMNotificationClient pClient);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void UnregisterEndpointNotificationCallback([MarshalAs(UnmanagedType.Interface)] [In] IMMNotificationClient pClient);
    }

    [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMDevice
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void Activate([In] ref Guid iid, [In] uint dwClsCtx, [In] IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OpenPropertyStore([In] uint stgmAccess, [MarshalAs(UnmanagedType.Interface)] out IPropertyStore ppProperties);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetId([MarshalAs(UnmanagedType.LPWStr)] out string ppstrId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetState(out uint pdwState);
    }

    [Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMNotificationClient
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId, [In] uint dwNewState);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDefaultDeviceChanged([ComAliasName("MMDevAPI.Interop.EDataFlow")] [In] EDataFlow flow, [ComAliasName("MMDevAPI.Interop.ERole")] [In] ERole role, [MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDefaultDeviceId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId, [In] PropertyKey key);
    }

    [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComImport]
    public interface IPropertyStore
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetCount(out uint cProps);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetAt([In] uint iProp, out PropertyKey pkey);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetValue([In] ref PropertyKey key, out PROPVARIANT pv);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void SetValue([In] ref PropertyKey key, [In] ref PROPVARIANT propvar);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void Commit();
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct PropertyKey
    {
        public static PropertyKey PKEY_Device_DeviceDesc = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 2 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_HardwareIds = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 3 }; // DEVPROP_TYPE_STRING_LIST
        public static PropertyKey PKEY_Device_Service = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 6 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_Class = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 9 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_Driver = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 11 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_ConfigFlags = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 12 }; // DEVPROP_TYPE_UINT32
        public static PropertyKey PKEY_Device_Manufacturer = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 13 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_FriendlyName = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 14 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_LocationInfo = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 15 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_Capabilities = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 17 }; // DEVPROP_TYPE_UNINT32
        public static PropertyKey PKEY_Device_BusNumber = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 23 }; // DEVPROP_TYPE_UINT32
        public static PropertyKey PKEY_Device_EnumeratorName = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 24 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_DevType = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 27 }; // DEVPROP_TYPE_UINT32
        public static PropertyKey PKEY_Device_Characteristics = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 29 }; // DEVPROP_TYPE_UINT32


        public static PropertyKey PKEY_Device_ManufacturerAttributes = new PropertyKey { fmtid = new Guid(unchecked((int)0x80d81ea6), unchecked((short)0x7473), 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b), pid = 4 }; // DEVPROP_TYPE_UINT32

        public static PropertyKey PKEY_DeviceClass_IconPath = new PropertyKey { fmtid = new Guid(unchecked((int)0x259abffc), 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66), pid = 12 }; // DEVPROP_TYPE_STRING_LIST

        public static PropertyKey PKEY_DeviceClass_ClassCoInstallers = new PropertyKey { fmtid = new Guid(unchecked((int)0x713d1703), 0xa2e2, 0x49f5, 0x92, 0x14, 0x56, 0x47, 0x2e, 0xf3, 0xda, 0x5c), pid = 2 }; // DEVPROP_TYPE_STRING_LIST

        public static PropertyKey PKEY_DeviceInterface_FriendlyName = new PropertyKey { fmtid = new Guid(unchecked((int)0x026e516e), 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22), pid = 2 }; // DEVPROP_TYPE_STRING

        public Guid fmtid;
        public uint pid;

        public static IEnumerable<PropertyKey> GetPropertyKeys()
        {
            var keyFields = typeof(PropertyKey).GetFields(BindingFlags.Public | BindingFlags.Static);
            return keyFields.Where(fieldInfo => fieldInfo.FieldType == typeof(PropertyKey))
                            .Select(fieldInfo => (PropertyKey)fieldInfo.GetValue(null));
        }

        public static string GetKeyName(PropertyKey propertyKey)
        {
            var keyFields = typeof(PropertyKey).GetFields(BindingFlags.Public | BindingFlags.Static);
            return keyFields.Select(fieldInfo => new { fieldInfo, value = (PropertyKey)fieldInfo.GetValue(null) })
                            .Where(@t => propertyKey.pid == @t.value.pid && propertyKey.fmtid == @t.value.fmtid)
                            .Select(@t => @t.fieldInfo.Name).FirstOrDefault();
        }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct PROPVARIANT
    {
        public ushort variantType;
        public byte wReserved1;
        public byte wReserved2;
        public uint wReserved3;
        public PROPVARIANTVALUE value;

        public object Value
        {
            get
            {
                switch ((VarEnum)variantType)
                {
                    case VarEnum.VT_EMPTY:
                        return null;
                    case VarEnum.VT_NULL:
                        return null;
                    case VarEnum.VT_VARIANT:
                        break;
                    case VarEnum.VT_DECIMAL:
                        return value.cyVal;
                    case VarEnum.VT_VOID:
                        break;
                    case VarEnum.VT_HRESULT:
                        break;
                    case VarEnum.VT_PTR:
                        break;
                    case VarEnum.VT_SAFEARRAY:
                        break;
                    case VarEnum.VT_CARRAY:
                        break;
                    case VarEnum.VT_USERDEFINED:
                        break;
                    case VarEnum.VT_RECORD:
                        break;
                    case VarEnum.VT_STREAM:
                        break;
                    case VarEnum.VT_STORAGE:
                        break;
                    case VarEnum.VT_STREAMED_OBJECT:
                        break;
                    case VarEnum.VT_STORED_OBJECT:
                        break;
                    case VarEnum.VT_BLOB_OBJECT:
                        break;
                    case VarEnum.VT_CF:
                        break;
                    case VarEnum.VT_CLSID:
                        return Marshal.PtrToStructure(value.pVal, typeof(Guid));
                    case VarEnum.VT_VECTOR:
                        break;
                    case VarEnum.VT_ARRAY:
                        break;
                    case VarEnum.VT_BYREF:
                        break;
                    case VarEnum.VT_I1:
                        return value.cVal;
                    case VarEnum.VT_UI1:
                        return value.bVal;
                    case VarEnum.VT_I2:
                        return value.iVal;
                    case VarEnum.VT_UI2:
                        return value.uiVal;
                    case VarEnum.VT_I4:
                    case VarEnum.VT_INT:
                        return value.intVal;
                    case VarEnum.VT_UI4:
                    case VarEnum.VT_UINT:
                        return value.uintVal;
                    case VarEnum.VT_I8:
                        return value.hVal;
                    case VarEnum.VT_UI8:
                        return value.uhVal;
                    case VarEnum.VT_R4:
                        return value.fltVal;
                    case VarEnum.VT_R8:
                        return value.dblVal;
                    case VarEnum.VT_BOOL:
                        return value.boolVal;
                    case VarEnum.VT_ERROR:
                        return value.scode;
                    case VarEnum.VT_CY:
                        return value.cyVal;
                    case VarEnum.VT_DATE:
                        return value.date;
                    case VarEnum.VT_FILETIME:
                        return DateTime.FromFileTime(value.hVal);
                    case VarEnum.VT_BSTR:
                        return Marshal.PtrToStringBSTR(value.pVal);
                    case VarEnum.VT_BLOB:
                        var blob = value.blob;
                        var blobData = new byte[blob.cbSize];
                        Marshal.Copy(blob.pBlobData, blobData, 0, (int)blob.cbSize);
                        return blobData;
                    case VarEnum.VT_LPSTR:
                        return Marshal.PtrToStringAnsi(value.pVal);
                    case VarEnum.VT_LPWSTR:
                        return Marshal.PtrToStringUni(value.pVal);
                    case VarEnum.VT_UNKNOWN:
                        return Marshal.GetObjectForIUnknown(value.pVal);
                    case VarEnum.VT_DISPATCH:
                        return value.pVal;
                    //default:
                    //    throw new NotSupportedException("The type of this variable is not support ('" + variantType + "')");
                }
                return string.Format("unsupported {0}", ((VarEnum)variantType));
                //throw new NotSupportedException("The type of this variable is not support ('" + variantType.ToString() + "')");
            }
        }
    }

    [ComConversionLoss]
    [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 8)]
    public struct PROPVARIANTVALUE
    {
        [FieldOffset(0)]
        public sbyte cVal;
        [FieldOffset(0)]
        public byte bVal;
        [FieldOffset(0)]
        public short iVal;
        [FieldOffset(0)]
        public ushort uiVal;
        [FieldOffset(0)]
        public int intVal;
        [FieldOffset(0)]
        public uint uintVal;
        [FieldOffset(0)]
        public long hVal;
        [FieldOffset(0)]
        public ulong uhVal;
        [FieldOffset(0)]
        public float fltVal;
        [FieldOffset(0)]
        public double dblVal;
        [FieldOffset(0)]
        public short boolVal;
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Error)]
        public int scode;
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Currency)]
        public decimal cyVal;
        [FieldOffset(0)]
        public DateTime date;
        [FieldOffset(0)]
        public tagFILETIME filetime;
        [FieldOffset(0)]
        public tagARRAY array;
        [FieldOffset(0)]
        public tagBLOB blob;
        [ComConversionLoss]
        [FieldOffset(0)]
        public IntPtr pVal;
    }

    [ComConversionLoss]
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct tagARRAY
    {
        public uint cElems;
        [ComConversionLoss]
        public IntPtr pElems;
    }

    [ComConversionLoss]
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct tagBLOB
    {
        public uint cbSize;
        [ComConversionLoss]
        public IntPtr pBlobData;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct tagFILETIME
    {
        public uint dwLowDateTime;
        public uint dwHighDateTime;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct tagLARGEINTEGER
    {
        public long QuadPart;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct tagULARGEINTEGER
    {
        public ulong QuadPart;
    }
}
person Dirk Vollmar    schedule 01.12.2015
comment
может ли кто-нибудь предоставить приведенный выше код в веб-приложении asp.net, мне нужно срочное требование, пожалуйста, предоставьте мне - person ; 04.07.2016
comment
@ user123: Какой браузер/платформа? В спецификации Web Audio API ничего не говорится об обнаружении таких аппаратных событий (см. stackoverflow.com/a/26085043/40347). . Возможно, вам повезет на некоторых мобильных платформах, но я бы в этом сильно сомневался. - person Dirk Vollmar; 04.07.2016
comment
могу ли я узнать, как я могу это сделать Наушники неправильно подключены к системе, которую я хочу отображать в предупреждающем сообщении в asp.net, не могли бы вы рассказать мне, как это сделать. подскажите пожалуйста как это сделать спасибо - person ; 05.07.2016
comment
Это будет работать только на английских системах. Имя конечной точки не будет «Наушники» на компьютерах, отличных от английского. - person Randall Deetz; 03.08.2016
comment
@RandallDeetz Код - это всего лишь пример, объясняющий, как программировать с помощью этого API. Образец фокусируется только на основных вещах и не касается локализации, обработки ошибок или чего-либо еще, что вы могли бы добавить в рабочую среду. - person Dirk Vollmar; 03.08.2016