I use Visual Studio 2013 for Visual Basic and I want to be able to test whether a speaker is plugged in or unplugged from the speaker jack. Is it possible?
            Asked
            
        
        
            Active
            
        
            Viewed 533 times
        
    1
            
            
        - 
                    http://stackoverflow.com/questions/33872895/detect-if-headphones-are-plugged-in-or-not-via-c-sharp – Ola Ekdahl Dec 12 '16 at 09:21
 - 
                    You can't detect it. Speaker ports are "dumb", they are simply passed audio and if something is plugged in, it passes down the wire to the speaker. Theres nothing in the jack to detect when something is plugged in im afraid. - I may stand corrected by Ola above! – LBPLC Dec 12 '16 at 09:22
 - 
                    From a quick read I think you basically can't. The link posted by Ola I think will detect when a device is added/removed (e.g. you add some USB speakers or something) but if you have a traditional sound card in the motherboard or installed into a PCI slot, and someone just unplugs the speakers/headphones, then no you can't detect it on a PC. Android phones seem to be able to tell, but presumably they have special hardware/software for this which isn't present on a PC. It's possible that some makes of sound cards do support this kind of thing, but it won't be a universal solution – ADyson Dec 12 '16 at 09:28
 - 
                    1You might be able to use access the drivers for your sound card, as some do detect when speakers are plugged in, but the code for it would specific to either that sound card or a limited group of cards from that particular manufacturer. That would of course need more research. – David Wilson Dec 12 '16 at 14:10
 
1 Answers
0
            
            
        It can be done with Device Topology API. IKsJackDescription interface can be used to get KSJACK_DESCRIPTION structure, which has IsConnected member. However, not every device supports cable presence detection, in case it doesn't the API will always report it's connected. 
COM objects declarations
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Runtime.CompilerServices
Namespace com_test
    Class Native
        <DllImport("ole32.Dll")> _
        Public Shared Function CoCreateInstance(ByRef clsid As Guid, <MarshalAs(UnmanagedType.IUnknown)> inner As Object, context As UInteger, ByRef uuid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByRef rReturnedComObject As Object) As UInteger
        End Function
        '************************************************************************
        <DllImport("ole32.dll")> _
        Private Shared Function PropVariantClear(ByRef pvar As PropVariant) As Integer
        End Function
        Public Const DEVICE_STATE_ACTIVE As Integer = &H1
        Public Const DEVICE_STATE_DISABLE As Integer = &H2
        Public Const DEVICE_STATE_NOTPRESENT As Integer = &H4
        Public Const DEVICE_STATE_UNPLUGGED As Integer = &H8
        Public Const DEVICE_STATEMASK_ALL As Integer = &Hf
        Public Shared PKEY_Device_FriendlyName As New PROPERTYKEY(&Ha45c254eUI, &Hdf1c, &H4efd, &H80, &H20, &H67, _
            &Hd1, &H46, &Ha8, &H50, &He0, 14)
        Public Shared PKEY_AudioEndpoint_FormFactor As New PROPERTYKEY(&H1da5d803, &Hd492, &H4edd, &H8c, &H23, &He0, _
            &Hc0, &Hff, &Hee, &H7f, &He, 0)
    End Class
    Enum EndpointFormFactor
        RemoteNetworkDevice = 0
        Speakers = (RemoteNetworkDevice + 1)
        LineLevel = (Speakers + 1)
        Headphones = (LineLevel + 1)
        Microphone = (Headphones + 1)
        Headset = (Microphone + 1)
        Handset = (Headset + 1)
        UnknownDigitalPassthrough = (Handset + 1)
        SPDIF = (UnknownDigitalPassthrough + 1)
        DigitalAudioDisplayDevice = (SPDIF + 1)
        UnknownFormFactor = (DigitalAudioDisplayDevice + 1)
        EndpointFormFactor_enum_count = (UnknownFormFactor + 1)
    End Enum
    Enum EPcxConnectionType
        eConnTypeUnknown = 0
        eConnType3Point5mm
        eConnTypeQuarter
        eConnTypeAtapiInternal
        eConnTypeRCA
        eConnTypeOptical
        eConnTypeOtherDigital
        eConnTypeOtherAnalog
        eConnTypeMultichannelAnalogDIN
        eConnTypeXlrProfessional
        eConnTypeRJ11Modem
        eConnTypeCombination
    End Enum
    Enum EPcxGeoLocation
        eGeoLocRear = &H1
        eGeoLocFront
        eGeoLocLeft
        eGeoLocRight
        eGeoLocTop
        eGeoLocBottom
        eGeoLocRearPanel
        eGeoLocRiser
        eGeoLocInsideMobileLid
        eGeoLocDrivebay
        eGeoLocHDMI
        eGeoLocOutsideMobileLid
        eGeoLocATAPI
        eGeoLocNotApplicable
        eGeoLocReserved6
        EPcxGeoLocation_enum_count
    End Enum
    Public Enum EDataFlow
        eRender
        eCapture
        eAll
        EDataFlow_enum_count
    End Enum
    Public Enum ERole
        eConsole
        eMultimedia
        eCommunications
        ERole_enum_count
    End Enum
    Public Enum CLSCTX
        CLSCTX_INPROC_SERVER = &H1
        CLSCTX_INPROC_HANDLER = &H2
        CLSCTX_LOCAL_SERVER = &H4
        CLSCTX_REMOTE_SERVER = &H10
        CLSCTX_SERVER = (CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER)
        CLSCTX_ALL = (CLSCTX_INPROC_HANDLER Or CLSCTX_SERVER)
    End Enum
    'Windows Core Audio API declarations
    'http://www.java2s.com/Code/CSharp/Windows/SoundUtils.htm
    <Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Public Interface IMMDeviceCollection
        Function GetCount(ByRef pcDevices As UInteger) As Integer
        Function Item(nDevice As UInteger, <Out, MarshalAs(UnmanagedType.[Interface])> ByRef ppDevice As Object) As Integer
    End Interface
    <Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Public Interface IMMDevice
        Function Activate(ByRef iid As Guid, dwClsCtx As UInteger, pActivationParams As IntPtr, <Out, MarshalAs(UnmanagedType.[Interface])> ByRef ppInterface As Object) As Integer
        Function OpenPropertyStore(stgmAccess As Integer, <Out, MarshalAs(UnmanagedType.[Interface])> ByRef ppProperties As Object) As Integer
        Function GetId(ByRef ppstrId As StringBuilder) As Integer
        Function GetState(ByRef pdwState As Integer) As Integer
    End Interface
    <ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")> _
    Class MMDeviceEnumerator
    End Class
    <Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Public Interface IMMDeviceEnumerator
        Function EnumAudioEndpoints(dataFlow As EDataFlow, dwStateMask As Integer, <Out, MarshalAs(UnmanagedType.[Interface])> ByRef ppDevices As Object) As Integer
        Function GetDefaultAudioEndpoint(dataFlow As EDataFlow, role As ERole, <Out, MarshalAs(UnmanagedType.[Interface])> ByRef ppEndpoint As Object) As Integer
        Function GetDevice(pwstrId As String, ByRef ppDevice As IntPtr) As Integer
        Function RegisterEndpointNotificationCallback(pClient As IntPtr) As Integer
        Function UnregisterEndpointNotificationCallback(pClient As IntPtr) As Integer
    End Interface
    '*********** Property store *****************************
    ' https://blogs.msdn.microsoft.com/adamroot/2008/04/11/interop-with-propvariants-in-net/
    <ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Interface IPropertyStore
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType := MethodCodeType.Runtime)> _
        Sub GetCount(<Out> ByRef cProps As UInteger)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType := MethodCodeType.Runtime)> _
        Sub GetAt(<[In]> iProp As UInteger, ByRef pkey As PROPERTYKEY)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType := MethodCodeType.Runtime)> _
        Function GetValue(<[In]> ByRef key As PROPERTYKEY, ByRef pv As PropVariant) As Integer
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType := MethodCodeType.Runtime)> _
        Sub SetValue(<[In]> ByRef key As PROPERTYKEY, <[In]> ByRef pv As Object)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType := MethodCodeType.Runtime)> _
        Sub Commit()
    End Interface
    <StructLayout(LayoutKind.Sequential, Pack := 4)> _
    Structure PROPERTYKEY
        Public fmtid As Guid
        Public pid As UInteger
        Public Sub New(guid As Guid, propertyId As Integer)
            Me.fmtid = guid
            Me.pid = CUInt(propertyId)
        End Sub
        Public Sub New(formatId As String, propertyId As Integer)
            Me.New(New Guid(formatId), propertyId)
        End Sub
        Public Sub New(a As UInteger, b As UInteger, c As UInteger, d As UInteger, e As UInteger, f As UInteger, _
            g As UInteger, h As UInteger, i As UInteger, j As UInteger, k As UInteger, propertyId As Integer)
            Me.New(New Guid(CUInt(a), CUShort(b), CUShort(c), CByte(d), CByte(e), CByte(f), _
                CByte(g), CByte(h), CByte(i), CByte(j), CByte(k)), propertyId)
        End Sub
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure PropVariant
        Private vt As UShort
        Private wReserved1 As UShort
        Private wReserved2 As UShort
        Private wReserved3 As UShort
        Private p As IntPtr
        Private p2 As Integer
        Private Function GetDataBytes() As Byte()
            Dim ret As Byte() = New Byte(IntPtr.Size + (4 - 1)) {}
            If IntPtr.Size = 4 Then
                BitConverter.GetBytes(p.ToInt32()).CopyTo(ret, 0)
            ElseIf IntPtr.Size = 8 Then
                BitConverter.GetBytes(p.ToInt64()).CopyTo(ret, 0)
            End If
            BitConverter.GetBytes(p2).CopyTo(ret, IntPtr.Size)
            Return ret
        End Function
        Private ReadOnly Property cVal() As SByte
            ' CHAR cVal;
            Get
                Return CSByte(GetDataBytes()(0))
            End Get
        End Property
        Private ReadOnly Property iVal() As Short
            ' SHORT iVal;
            Get
                Return BitConverter.ToInt16(GetDataBytes(), 0)
            End Get
        End Property
        Private ReadOnly Property lVal() As Integer
            ' LONG lVal;
            Get
                Return BitConverter.ToInt32(GetDataBytes(), 0)
            End Get
        End Property
        Private ReadOnly Property hVal() As Long
            ' LARGE_INTEGER hVal;
            Get
                Return BitConverter.ToInt64(GetDataBytes(), 0)
            End Get
        End Property
        Private ReadOnly Property fltVal() As Single
            ' FLOAT fltVal;
            Get
                Return BitConverter.ToSingle(GetDataBytes(), 0)
            End Get
        End Property
        Public ReadOnly Property Value() As Object
            Get
                Select Case CType(vt, VarEnum)
                    Case VarEnum.VT_I1
                        Return cVal
                    Case VarEnum.VT_I2
                        Return iVal
                    Case VarEnum.VT_I4, VarEnum.VT_INT
                        Return lVal
                    Case VarEnum.VT_UI4, VarEnum.VT_I8
                        Return hVal
                    Case VarEnum.VT_R4
                        Return fltVal
                    Case VarEnum.VT_FILETIME
                        Return DateTime.FromFileTime(hVal)
                    Case VarEnum.VT_BSTR
                        Return Marshal.PtrToStringBSTR(p)
                    Case VarEnum.VT_BLOB
                        Dim blobData As Byte() = New Byte(lVal - 1) {}
                        Dim pBlobData As IntPtr
                        If IntPtr.Size = 4 Then
                            pBlobData = New IntPtr(p2)
                        ElseIf IntPtr.Size = 8 Then
                            pBlobData = New IntPtr(BitConverter.ToInt64(GetDataBytes(), 4))
                        Else
                            Throw New NotSupportedException()
                        End If
                        Marshal.Copy(pBlobData, blobData, 0, lVal)
                        Return blobData
                    Case VarEnum.VT_LPSTR
                        Return Marshal.PtrToStringAnsi(p)
                    Case VarEnum.VT_LPWSTR
                        Return Marshal.PtrToStringUni(p)
                    Case VarEnum.VT_UNKNOWN
                        Return Marshal.GetObjectForIUnknown(p)
                    Case VarEnum.VT_DISPATCH
                        Return p
                    Case Else
                        Throw New NotSupportedException("0x" + vt.ToString("X4") + " type not supported")
                End Select
            End Get
        End Property
    End Structure
    '*****************************************************
    'Device Topology declarations
    <Guid("2A07407E-6497-4A18-9787-32F79BD0D98F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Public Interface IDeviceTopology
        Function GetConnectorCount(<Out> ByRef pConnectorCount As Integer) As Integer
        Function GetConnector(nIndex As Integer, ByRef ppConnector As IConnector) As Integer
        Function GetSubunitCount(<Out> ByRef pCount As Integer) As Integer
        'ISubunit
        Function GetSubunit(nIndex As Integer, ByRef ppSubunit As Object) As Integer
        Function GetPartById(nId As Integer, ByRef ppPart As IPart) As Integer
        Function GetDeviceId(<Out, MarshalAs(UnmanagedType.LPWStr)> ByRef ppwstrDeviceId As String) As Integer
        'IPartsList
        Function GetSignalPath(pIPartFrom As IPart, pIPartTo As IPart, bRejectMixedPaths As Boolean, ppParts As Object) As Integer
    End Interface
    <InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("9c2c4058-23f5-41de-877a-df3af236a09e")> _
    Public Interface IConnector
        Function [GetType](ByRef pType As Integer) As Integer
        Function GetDataFlow(ByRef dataFlow As EDataFlow) As Integer
        Function ConnectTo(<[In]> connector As IConnector) As Integer
        Function Disconnect() As Integer
        Function IsConnected(ByRef pbConnected As Boolean) As Integer
        Function GetConnectedTo(<MarshalAs(UnmanagedType.[Interface])> ByRef ppConTo As Object) As Integer
        Function GetConnectorIdConnectedTo(ByRef ppwstrConnectorId As String) As Integer
        Function GetDeviceIdConnectedTo(ByRef ppwstrDeviceId As String) As Integer
    End Interface
    <Guid("AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Public Interface IPart
        Function GetName(ByRef ppwstrName As StringBuilder) As Integer
        Function GetLocalId(ByRef pnId As Integer) As Integer
        Function GetGlobalId(ByRef ppwstrGlobalId As StringBuilder) As Integer
        Function GetPartType(ByRef pPartType As Integer) As Integer
        Function GetSubType(ByRef pSubType As Guid) As Integer
        Function GetControlInterfaceCount(ByRef pCount As UInteger) As Integer
        'IControlInterface
        Function GetControlInterface(nIndex As Integer, ByRef ppFunction As Object) As Integer
        'IPartsList[]
        Function EnumPartsIncoming(ByRef ppParts As Object) As Integer
        'IPartsList[]
        Function EnumPartsOutgoing(ByRef ppParts As Object) As Integer
        Function GetTopologyObject(<Out, MarshalAs(UnmanagedType.[Interface])> ByRef ppTopology As Object) As Integer
        Function Activate(dwClsContext As UInteger, ByRef refiid As Guid, <MarshalAs(UnmanagedType.[Interface])> ByRef interfacePointer As Object) As Integer
        'IControlChangeNotify
        Function RegisterControlChangeCallback(ByRef riid As Guid, pNofity As Object) As Integer
        'IControlChangeNotify
        Function UnregisterControlChangeCallback(pNotify As Object) As Integer
    End Interface
    <ComVisible(False)> _
    <ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("4509F757-2D46-4637-8E62-CE7DB944F57B")> _
    Public Interface IKsJackDescription
        Function GetJackCount(ByRef jacks As UInteger) As Integer
        Function GetJackDescription(jack As UInteger, ByRef pDescription As KSJACK_DESCRIPTION) As Integer
    End Interface
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure KSJACK_DESCRIPTION
        Public ChannelMapping As UInteger
        Public Color As UInteger
        Public ConnectionType As UInteger
        Public GeoLocation As UInteger
        Public GenLocation As UInteger
        Public PortConnection As UInteger
        Public IsConnected As UInteger
    End Structure
End Namespace
Example how to get info about current default device's jack information
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Namespace com_test
    Public Partial Class Form1
        Inherits Form
        'displays device
        Private Function PrintDevice(dev As IMMDevice) As String
            Dim propertyStore As IPropertyStore = Nothing
            Dim pDeviceTopology As IDeviceTopology = Nothing
            Dim pConnFrom As IConnector = Nothing
            Dim pConnTo As IConnector = Nothing
            Dim pPart As IPart = Nothing
            Dim pJackDesc As IKsJackDescription = Nothing
            Dim desc As New KSJACK_DESCRIPTION()
            Dim res As New StringBuilder(300)
            Dim o As Object = Nothing
            Dim state As Integer = 0
            Dim con_count As UInteger = 0
            Try
                'device name
                'STGM_READ
                dev.OpenPropertyStore(0, o)
                propertyStore = TryCast(o, IPropertyStore)
                Dim friendlyName As New PropVariant()
                propertyStore.GetValue(Native.PKEY_Device_FriendlyName, friendlyName)
                res.AppendLine(friendlyName.Value.ToString())
                'form factor 
                Dim FormFactor As New PropVariant()
                propertyStore.GetValue(Native.PKEY_AudioEndpoint_FormFactor, FormFactor)
                Dim f As EndpointFormFactor = EndpointFormFactor.UnknownFormFactor
                [Enum].TryParse(Of EndpointFormFactor)(FormFactor.Value.ToString(), f)
                res.AppendLine("Form factor: " + f.ToString())
                dev.GetState(state)
                Dim str As String = ""
                Select Case state
                    Case Native.DEVICE_STATE_DISABLE
                        str = ("Disabled")
                        Exit Select
                    Case Native.DEVICE_STATE_NOTPRESENT
                        str = ("Not present")
                        Exit Select
                    Case Native.DEVICE_STATE_UNPLUGGED
                        str = ("Unplugged")
                        Exit Select
                End Select
                If str <> "" Then
                    res.AppendLine(str)
                End If
                ' DEVICE TOPOLOGY 
                Dim iidDeviceTopology As New Guid("2A07407E-6497-4A18-9787-32F79BD0D98F")
                dev.Activate(iidDeviceTopology, CUInt(CLSCTX.CLSCTX_ALL), IntPtr.Zero, o)
                pDeviceTopology = TryCast(o, IDeviceTopology)
                pDeviceTopology.GetConnector(0, pConnFrom)
                Try
                    o = Nothing
                    pConnFrom.GetConnectedTo(o)
                    pConnTo = TryCast(o, IConnector)
                    pPart = CType(pConnTo, IPart)
                    'QueryInterface
                    Dim iidKsJackDescription As New Guid("4509F757-2D46-4637-8E62-CE7DB944F57B")
                    pPart.Activate(CUInt(CLSCTX.CLSCTX_INPROC_SERVER), iidKsJackDescription, o)
                    pJackDesc = CType(o, IKsJackDescription)
                    If pJackDesc IsNot Nothing Then
                        con_count = 0
                        pJackDesc.GetJackCount(con_count)
                        If con_count > 0 Then
                            Dim sb As StringBuilder
                            'display jacks
                            For i As UInteger = 0 To con_count - 1
                                pJackDesc.GetJackDescription(i, desc)
                                sb = New StringBuilder(100)
                                Dim con_type As EPcxConnectionType = CType(desc.ConnectionType, EPcxConnectionType)
                                Dim loc As EPcxGeoLocation = CType(desc.GeoLocation, EPcxGeoLocation)
                                res.Append("* ")
                                Select Case con_type
                                    Case EPcxConnectionType.eConnType3Point5mm
                                        sb.Append("Jack 3.5 mm ")
                                        Exit Select
                                    Case EPcxConnectionType.eConnTypeAtapiInternal
                                        sb.Append("ATAPI jack")
                                        Exit Select
                                    Case EPcxConnectionType.eConnTypeRCA
                                        sb.Append("RCA jack")
                                        Exit Select
                                    Case EPcxConnectionType.eConnTypeQuarter
                                        sb.Append("1/2 in. jack ")
                                        Exit Select
                                    Case EPcxConnectionType.eConnTypeOtherAnalog
                                        sb.Append("Analog jack ")
                                        Exit Select
                                    Case EPcxConnectionType.eConnTypeOtherDigital
                                        sb.Append("Digital jack ")
                                        Exit Select
                                    Case Else
                                        sb.Append(con_type.ToString() + " ")
                                        Exit Select
                                End Select
                                sb.Append("- " + loc.ToString())
                                'jack location
                                res.Append(sb.ToString())
                                If desc.IsConnected = 0 Then
                                    res.AppendLine(": Disconnected")
                                Else
                                    res.AppendLine(": Connected")
                                End If
                                'end for
                            Next
                        Else
                            res.AppendLine("* No jacks")
                        End If
                    Else
                        res.AppendLine("* Unable to get jacks")
                    End If
                Catch ex As COMException
                    If CUInt(ex.HResult) = &H80070490UI Then
                        'E_NOTFOUND
                        res.AppendLine("Disconnected")
                    Else
                        res.AppendLine("COM error while getting jacks: " + ex.Message)
                    End If
                Catch ex As Exception
                    res.AppendLine("Error while getting jacks: " + ex.Message)
                End Try
            Finally
                'clean up resources                
                If dev IsNot Nothing Then
                    Marshal.ReleaseComObject(dev)
                End If
                If propertyStore IsNot Nothing Then
                    Marshal.ReleaseComObject(propertyStore)
                End If
                If pDeviceTopology IsNot Nothing Then
                    Marshal.ReleaseComObject(pDeviceTopology)
                    pDeviceTopology = Nothing
                End If
                If pConnFrom IsNot Nothing Then
                    Marshal.ReleaseComObject(pConnFrom)
                    pConnFrom = Nothing
                End If
                If pConnTo IsNot Nothing Then
                    Marshal.ReleaseComObject(pConnTo)
                    pConnTo = Nothing
                End If
                If pPart IsNot Nothing Then
                    Marshal.ReleaseComObject(pPart)
                    pPart = Nothing
                End If
                If pJackDesc IsNot Nothing Then
                    Marshal.ReleaseComObject(pJackDesc)
                    pJackDesc = Nothing
                End If
            End Try
            Return res.ToString()
        End Function
        Public Sub New()
            InitializeComponent()
        End Sub
        Private Sub button_Click(sender As Object, e As EventArgs)
            Dim devenum As New MMDeviceEnumerator()
            'Create enumerator
            Dim deviceEnumerator As IMMDeviceEnumerator = CType(devenum, IMMDeviceEnumerator)
            Dim defDevice As IMMDevice = Nothing
            Dim propertyStore As IPropertyStore = Nothing
            Try
                Dim o As Object = Nothing
                ' * get default device *                
                deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, o)
                defDevice = TryCast(o, IMMDevice)
                textBox1.Text = "Default sound device: " + Environment.NewLine + Environment.NewLine
                textBox1.Text += PrintDevice(defDevice)
            Catch ex As Exception
                MessageBox.Show(ex.ToString())
            Finally
                'clean up resources
                If devenum IsNot Nothing Then
                    Marshal.ReleaseComObject(devenum)
                End If
                If deviceEnumerator IsNot Nothing Then
                    Marshal.ReleaseComObject(deviceEnumerator)
                End If
                If defDevice IsNot Nothing Then
                    Marshal.ReleaseComObject(defDevice)
                End If
                If propertyStore IsNot Nothing Then
                    Marshal.ReleaseComObject(propertyStore)
                End If
            End Try
        End Sub
    End Class
End Namespace
        MSDN.WhiteKnight
        
- 664
 - 7
 - 30