GetIfTable Pointers in VB.NET

element

Active member
Joined
Oct 29, 2003
Messages
26
Location
Portsmouth, UK
Hi,

Ive been attempting to get this to work for around 5 hours now, getting a little tired of it failing me :S

Please can somebody tell me where Im going wrong, actually - I know where Im going wrong but I dont know how to fix it.

Code:
    <StructLayout(LayoutKind.Sequential)> Public Class MIB_IFTABLE
        Public dwNumEntries As Integer
        <MarshalAs(UnmanagedType.SafeArray)> Public table() As MIB_IFROW
    End Class

    <StructLayout(LayoutKind.Sequential)> Public Class MIB_IFROW
        <VBFixedArray(511)> Public wszName() As Byte 511
        Public wszName As Byte()
        Public dwIndex As Int32
        Public dwType As Int32
        Public dwMtu As Int32
        Public dwSpeed As Int32
        Public dwPhysAddrLen As Int32
        <VBFixedArray(7)> Public bPhysAddr() As Byte 7
        Public bPhysAddr() As Byte
        Public dwAdminStatus As Int32
        Public dwOperStatus As Int32
        Public dwLastChange As Int32
        Public dwInOctets As Int32
        Public dwInUcastPkts As Int32
        Public dwInNUcastPkts As Int32
        Public dwInDiscards As Int32
        Public dwInErrors As Int32
        Public dwInUnknownProtos As Int32
        Public dwOutOctets As Int32
        Public dwOutUcastPkts As Int32
        Public dwOutNUcastPkts As Int32
        Public dwOutDiscards As Int32
        Public dwOutErrors As Int32
        Public dwOutQLen As Int32
        Public dwDescrLen As Int32
        <VBFixedArray(255)> Public bDescr() As Byte 255
        Public bDescr() As Byte
    End Class

Above are the classes used. I cannot use Structures for some reason, it says:

Additional information: Can not marshal field table of type MIB_IFTABLE: This type can not be marshaled as a structure field.

(Note this only happens when I un-comment out the table variable in the MIB_IFTABLE structure)

This is the error I get with the code I use below:

An unhandled exception of type System.Runtime.InteropServices.SafeArrayTypeMismatchException occurred in mscorlib.dll

Additional information: Mismatch has occurred between the runtime type of the array and the sub type recorded in the metadata.

Code:
        Dim lRetSize As Int32, lRows As Int32, ret As Long
        Dim IfRowTable As New MIB_IFTABLE
        Dim pStruct As IntPtr = IntPtr.Zero

        ret = GetIfTable(pStruct, lRetSize, 0)
        pStruct = Marshal.AllocHGlobal(lRetSize)

        ret = GetIfTable(pStruct, lRetSize, 0)
        IfRowTable = Marshal.PtrToStructure(pStruct, GetType(MIB_IFTABLE))
        Marshal.FreeHGlobal(pStruct)

It is strange, because when I comment out the table variable, it gives me the value of 1311096 in dwNumEntries. This value *should* be two (2 network devices, loopback + NIC)

Thank you for any help/advice in advance, Tom
 
Alright Ive figured it all out, in fact, I did so like 2 hours after my original post. Ill paste in the code for a class I have written.

Code:
Imports System.Runtime.InteropServices

Class clsNetworkStats

#Region " DECLARES "

    Private Const MAX_INTERFACE_NAME_LEN As Long = 256
    Private Const ERROR_SUCCESS As Long = 0
    Private Const MAXLEN_IFDESCR As Long = 256
    Private Const MAXLEN_PHYSADDR As Long = 8

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> Private Structure MIB_IFROW
        <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=MAX_INTERFACE_NAME_LEN)> Public wszName As String
        Public dwIndex As UInt32
        Public dwType As UInt32
        Public dwMtu As UInt32
        Public dwSpeed As UInt32
        Public dwPhysAddrLen As UInt32
        <MarshalAs(UnmanagedType.ByValArray, sizeconst:=MAXLEN_PHYSADDR)> Public bPhysAddr() As Byte
        Public dwAdminStatus As UInt32
        Public dwOperStatus As UInt32
        Public dwLastChange As UInt32
        Public dwInOctets As UInt32
        Public dwInUcastPkts As UInt32
        Public dwInNUcastPkts As UInt32
        Public dwInDiscards As UInt32
        Public dwInErrors As UInt32
        Public dwInUnknownProtos As UInt32
        Public dwOutOctets As UInt32
        Public dwOutUcastPkts As UInt32
        Public dwOutNUcastPkts As UInt32
        Public dwOutDiscards As UInt32
        Public dwOutErrors As UInt32
        Public dwOutQLen As UInt32
        Public dwDescrLen As UInt32
        <MarshalAs(UnmanagedType.ByValArray, sizeconst:=MAXLEN_IFDESCR)> Public bDescr() As Byte
    End Structure

    Public Structure IFROW_HELPER
        Public Name As String
        Public Index As Integer
        Public Type As Integer
        Public Mtu As Integer
        Public Speed As Integer
        Public PhysAddrLen As Integer
        Public PhysAddr As String
        Public AdminStatus As Integer
        Public OperStatus As Integer
        Public LastChange As Integer
        Public InOctets As Integer
        Public InUcastPkts As Integer
        Public InNUcastPkts As Integer
        Public InDiscards As Integer
        Public InErrors As Integer
        Public InUnknownProtos As Integer
        Public OutOctets As Integer
        Public OutUcastPkts As Integer
        Public OutNUcastPkts As Integer
        Public OutDiscards As Integer
        Public OutErrors As Integer
        Public OutQLen As Integer
        Public Description As String
        Public InMegs As String
        Public OutMegs As String
    End Structure

    <DllImport("iphlpapi")> Private Shared Function GetIfTable(ByRef pIfRowTable As Byte, ByRef pdwSize As Int32, ByVal bOrder As Int32) As Int32
    End Function

    <DllImport("iphlpapi")> Private Shared Function GetIfEntry(ByRef pIfRow As MIB_IFROW) As Int32
    End Function

#End Region

    Private m_Adapters As ArrayList

    Public Sub New(Optional ByVal IgnoreLoopBack As Boolean = True)

        Dim lRetSize As Int32, lRows As Int32, ret As Long, i As Byte
        Dim ifrow As New MIB_IFROW
        Dim buff(0) As Byte

        --////////////////////////////////////////////////////////////////////////////////////////////
        ret = GetIfTable(0&, lRetSize, 0)
        ret = GetIfTable(buff(0), lRetSize, 0)
        lRows = buff(0)

        m_Adapters = New ArrayList(lRows)

        For i = 1 To lRows
            ifrow = New MIB_IFROW
            ifrow.dwIndex = Convert.ToUInt32(i)
            ret = GetIfEntry(ifrow)
            Dim ifhelp As IFROW_HELPER = PrivToPub(ifrow)
            If IgnoreLoopBack = True Then
                If ifhelp.Description.IndexOf("Loopback") < 0 Then
                    m_Adapters.Add(ifhelp)
                End If
            Else
                m_Adapters.Add(ifhelp)
            End If
        Next
        --////////////////////////////////////////////////////////////////////////////////////////////

    End Sub

    Public Function GetAdapter(ByVal index As Integer) As IFROW_HELPER

        Return m_Adapters(index)

    End Function

    <DebuggerStepThrough()> Private Function PrivToPub(ByVal pri As MIB_IFROW) As IFROW_HELPER

        Dim ifhelp As New IFROW_HELPER

        ifhelp.Name = pri.wszName.Trim
        ifhelp.Index = Convert.ToInt32(pri.dwIndex)
        ifhelp.Type = Convert.ToInt32(pri.dwType)
        ifhelp.Mtu = Convert.ToInt32(pri.dwMtu)
        ifhelp.Speed = Convert.ToInt32(pri.dwSpeed)
        ifhelp.PhysAddrLen = Convert.ToInt32(pri.dwPhysAddrLen)
        ifhelp.PhysAddr = System.Text.Encoding.ASCII.GetString(pri.bPhysAddr)
        ifhelp.AdminStatus = Convert.ToInt32(pri.dwAdminStatus)
        ifhelp.OperStatus = Convert.ToInt32(pri.dwOperStatus)
        ifhelp.LastChange = Convert.ToInt32(pri.dwLastChange)
        ifhelp.InOctets = Convert.ToInt32(pri.dwInOctets)
        ifhelp.InUcastPkts = Convert.ToInt32(pri.dwInUcastPkts)
        ifhelp.InNUcastPkts = Convert.ToInt32(pri.dwInNUcastPkts)
        ifhelp.InDiscards = Convert.ToInt32(pri.dwInDiscards)
        ifhelp.InErrors = Convert.ToInt32(pri.dwInErrors)
        ifhelp.InUnknownProtos = Convert.ToInt32(pri.dwInUnknownProtos)
        ifhelp.OutOctets = Convert.ToInt32(pri.dwOutOctets)
        ifhelp.OutUcastPkts = Convert.ToInt32(pri.dwOutUcastPkts)
        ifhelp.OutNUcastPkts = Convert.ToInt32(pri.dwOutNUcastPkts)
        ifhelp.OutDiscards = Convert.ToInt32(pri.dwOutDiscards)
        ifhelp.OutErrors = Convert.ToInt32(pri.dwOutErrors)
        ifhelp.OutQLen = Convert.ToInt32(pri.dwOutQLen)
        ifhelp.Description = System.Text.Encoding.ASCII.GetString(pri.bDescr, 0, Convert.ToInt32(pri.dwDescrLen))

        ifhelp.InMegs = ToMegs(ifhelp.InOctets)
        ifhelp.OutMegs = ToMegs(ifhelp.OutOctets)

        Return ifhelp

    End Function

    <DebuggerStepThrough()> Private Function ToMegs(ByVal lSize As Long) As String

        Dim sDenominator As String = " B"
        If lSize > 1024 Then lSize = (lSize / 1024) * 1000 Windows styleee filesizing :)
        If lSize > 1000 Then
            sDenominator = " KB"
            lSize = lSize / 1000
        ElseIf lSize <= 1000 Then
            sDenominator = " B"
            lSize = lSize
        End If

        ToMegs = Format(lSize, "###,###0") & sDenominator

    End Function

End Class
 
Back
Top