Funktion GetIfTable aus der Iphlpapi.dll

  • Habe ein Problem mit dem Aufruf der Funktion. Ich bekomme als Fehlercode 122 - ERROR_INSUFFICIENT_BUFFER zurück.
    Auch weiß ich nicht ob die beiden Strukturen $MIB_IFTABLE und $MIB_IFROW so richtig verschachtelt sind.

    Hätte jemand einen Tipp für mich? Würde mich echt freuen besonders da ich grade erst angefangen hab mich mit api Funktionen zu beschäftigen.

    Spoiler anzeigen
    [autoit]

    $str = "byte wszName[510];long dwIndex;long dwtype;long dwMTU;long dwSpeed;long dwPhysAddrLen;byte bPhysAddr[7];long dwAdminStatus;long dwOperStatus;long dwLastChange;"
    $str = $str & "long dwInOctets;long dwInUcastPkts;long dwInNUcastPkts;long dwInDiscards;long dwInErrors;long dwInUnknownProtos;long dwOutOctets;long dwOutUcastPkts;"
    $str = $str & "long dwOutNUcastPkts;long dwOutDiscards;long dwOutErrors;long dwOutQLen;long dwDescrLen;byte bDescr[255]"
    $MIB_IFROW = DllStructCreate($str)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $MIB_IFTABLE = DllStructCreate("long dwNumEntries;" & $MIB_IFROW)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $err = DllCall("Iphlpapi.dll", "dword","GetIfTable","ptr", DllStructGetPtr($MIB_IFTABLE), "long*", DllStructGetSize($MIB_IFTABLE),"int",1)

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay($err)

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0,$err,DllStructGetData($MIB_IFTABLE, "dwNumEntries"))

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    EndFunc

    [/autoit]

    Einmal editiert, zuletzt von Bitboy (2. April 2009 um 17:50)

  • Soweit bin ich schon mal, Die Informationen der Netzwerkkarten stehen in dem Puffer drin, zu sehen ist das in der Datei die angelegt wird.
    Dort sind zumindest die Namen der Karten erkennbar.

    Wie schaffe ich es jetzt jedoch die informationen in die Struktur zu packen? und auszulesen.

    Das mit dem RTLMoveMemory habe ich aus einem Tipp von ActiveVB, jedoch lässt es sich nicht so einfach umschreiben.

    Helfen würde es wohl auch schon wenn ich wüsste wie ich strukturen verschachtel.

    Spoiler anzeigen
    [autoit]

    Func _GetNetUsage()
    ;Netzwerk Adapter Typen
    Const $MIB_IF_TYPE_OTHER = 1 ;Some other type of network interface.
    Const $MIB_IF_TYPE_ETHERNET = 6 ;An Ethernet network interface.
    Const $MIB_IF_TYPE_TOKENRING = 9 ;A token ring network interface.
    Const $MIB_IF_TYPE_PPP = 23 ;A PPP network interface.
    Const $MIB_IF_TYPE_LOOPBACK = 24 ;A software loopback network interface.
    Const $MIB_IF_TYPE_ATM = 37 ;An ATM network interface.
    Const $MIB_IF_TYPE_IEEE80211 = 73 ;An IEEE 802.11 wireless network interface.
    Const $MIB_IF_TYPE_TUNNEL = 131 ;A tunnel type encapsulation network interface.
    Const $MIB_IF_TYPE_IEEE1394 = 144 ;An IEEE 1394 (Firewire) high performance serial bus network interface.

    [/autoit] [autoit][/autoit] [autoit]

    ;Variablendeklaration
    Dim $puffersize, $StructSize, $AdapterCount
    Dim $puffer

    [/autoit] [autoit][/autoit] [autoit]

    ;Erstellen der Struktur MIB_IFROW
    $str = "byte wszName[510];long dwIndex;long dwtype;long dwMTU;long dwSpeed;long dwPhysAddrLen;byte bPhysAddr[7];long dwAdminStatus;long dwOperStatus;long dwLastChange;"
    $str = $str & "long dwInOctets;long dwInUcastPkts;long dwInNUcastPkts;long dwInDiscards;long dwInErrors;long dwInUnknownProtos;long dwOutOctets;long dwOutUcastPkts;"
    $str = $str & "long dwOutNUcastPkts;long dwOutDiscards;long dwOutErrors;long dwOutQLen;long dwDescrLen;byte bDescr[255]"
    $MIB_IFROW = DllStructCreate($str)

    [/autoit] [autoit][/autoit] [autoit]

    ;Erstellen der Struktur MIB_IFTABLE
    $MIB_IFTABLE = DllStructCreate("long dwNumEntries;")

    [/autoit] [autoit][/autoit] [autoit]

    ;Erster Aufruf (wird fehlschlagen) liefert dabei aber die benötigte Puffergröße
    $err = DllCall("Iphlpapi.dll", "dword","GetIfTable","ptr", DllStructGetPtr($MIB_IFTABLE), "long*", DllStructGetSize($MIB_IFTABLE),"long",1)

    [/autoit] [autoit][/autoit] [autoit]

    ;Puffergröße bestimmen
    If IsArray($err) Then
    If $err[0] = 122 Then ;Fehler: Puffer zu klein
    $puffersize = $err[2]
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;Erstellen der Struktur MIB_IFTABLE mit passender Puffergröße
    $MIB_IFTABLE = 0
    $MIB_IFTABLE = DllStructCreate("long dwNumEntries;byte puffer[" & $puffersize &"]")

    [/autoit] [autoit][/autoit] [autoit]

    ;Zweiter Aufruf
    $err = DllCall("Iphlpapi.dll", "dword","GetIfTable","ptr", DllStructGetPtr($MIB_IFTABLE), "long*", DllStructGetSize($MIB_IFTABLE),"long",1)

    [/autoit] [autoit][/autoit] [autoit]

    ;Größe der Struktur und die Anzahl der Adapter speichern
    $StructSize = DllStructGetSize($MIB_IFROW)
    $AdapterCount = DllStructGetData($MIB_IFTABLE, "dwNumEntries")

    [/autoit] [autoit][/autoit] [autoit]

    ;Testdatei schreiben
    $a=FileOpen("C:\test.txt",2)
    FileWrite($a,(DllStructGetData($MIB_IFTABLE, "puffer")))
    FileClose($a)

    [/autoit] [autoit][/autoit] [autoit]

    $puffer = Stringtoasciiarray(DllStructGetData($MIB_IFTABLE, "puffer"))

    [/autoit] [autoit][/autoit] [autoit]

    $MIB_IFTABLE = 0

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 to $AdapterCount
    $err = DllCall("kernel32", "none","RtlMoveMemory","ptr", DllStructGetPtr($MIB_IFROW), "byte*", Ptr($puffer[4+($i - 1) * $StructSize]),"ulong",$StructSize)

    MsgBox(0,"bPhysAddr",DllStructGetData($MIB_IFROW, "bPhysAddr"))
    Next

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    _GetNetUsage()

    [/autoit]

    Einmal editiert, zuletzt von Bitboy (2. April 2009 um 12:51)

  • Du kannst es z.B. so machen: die Strukturen werden in dem Puffer hintereinander geschrieben. Dann erstellst du einfach jedes Mal eine Neue DLLStruct an der gewünschten Stelle. Mit DLLStructGetPtr($MIB_TABLE, "puffer") holst du den Pointer zum Puffer. Die erste Struktur fängt direkt dirt an. Die n-te Struktur ist dann Pointer + (n-1)*StrukturGröße

    Spoiler anzeigen
    [autoit]

    ;Netzwerk Adapter Typen
    Global Const $MIB_IF_TYPE_OTHER = 1 ;Some other type of network interface.
    Global Const $MIB_IF_TYPE_ETHERNET = 6 ;An Ethernet network interface.
    Global Const $MIB_IF_TYPE_TOKENRING = 9 ;A token ring network interface.
    Global Const $MIB_IF_TYPE_PPP = 23 ;A PPP network interface.
    Global Const $MIB_IF_TYPE_LOOPBACK = 24 ;A software loopback network interface.
    Global Const $MIB_IF_TYPE_ATM = 37 ;An ATM network interface.
    Global Const $MIB_IF_TYPE_IEEE80211 = 73 ;An IEEE 802.11 wireless network interface.
    Global Const $MIB_IF_TYPE_TUNNEL = 131 ;A tunnel type encapsulation network interface.
    Global Const $MIB_IF_TYPE_IEEE1394 = 144 ;An IEEE 1394 (Firewire) high performance serial bus network interface.

    [/autoit] [autoit][/autoit] [autoit]

    ;Variablendeklaration
    Dim $puffersize, $StructSize, $AdapterCount
    Dim $puffer

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $MAX_INTERFACE_NAME_LEN = 256
    Global Const $MAXLEN_IFDESCR = 256
    Global Const $MAXLEN_PHYSADDR = 8

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $tagMIB_IFROW = _
    "WCHAR wszName[" & $MAX_INTERFACE_NAME_LEN & "]; " & _
    "DWORD dwIndex;" & _
    "DWORD dwType;" & _
    "DWORD dwMtu;" & _
    "DWORD dwSpeed;" & _
    "DWORD dwPhysAddrLen;" & _
    "BYTE bPhysAddr[" & $MAXLEN_PHYSADDR & "];" & _
    "DWORD dwAdminStatus;" & _
    "DWORD dwOperStatus;" & _
    "DWORD dwLastChange;" & _
    "DWORD dwInOctets;" & _
    "DWORD dwInUcastPkts;" & _
    "DWORD dwInNUcastPkts;" & _
    "DWORD dwInDiscards;" & _
    "DWORD dwInErrors;" & _
    "DWORD dwInUnknownProtos;" & _
    "DWORD dwOutOctets;" & _
    "DWORD dwOutUcastPkts;" & _
    "DWORD dwOutNUcastPkts;" & _
    "DWORD dwOutDiscards;" & _
    "DWORD dwOutErrors;" & _
    "DWORD dwOutQLen;" & _
    "DWORD dwDescrLen;" & _
    "BYTE bDescr[" & $MAXLEN_IFDESCR & "];"

    [/autoit] [autoit][/autoit] [autoit]

    ;Deklaration der Struktur MIB_IFTABLE
    Global Const $tagMIB_IFTABLE_HEADER = "DWORD dwNumEntries;"

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _GetNetUsage()
    Local $puffersize = 0

    [/autoit] [autoit][/autoit] [autoit]

    ;Erster Aufruf (wird fehlschlagen) liefert dabei aber die benötigte Puffergröße
    Local $err = DllCall("Iphlpapi.dll", "dword","GetIfTable","ptr", 0, "ulong*", 0,"long",1)
    If Not @error Then
    If $err[0] = 122 Then ;Fehler: Puffer zu klein
    $puffersize = $err[2]
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;Erstellen der Struktur MIB_IFTABLE mit passender Puffergröße
    Local $MIB_IFTABLE = DllStructCreate($tagMIB_IFTABLE_HEADER & "byte puffer[" & $puffersize &"]")

    [/autoit] [autoit][/autoit] [autoit]

    ;Zweiter Aufruf
    $err = DllCall("Iphlpapi.dll", "dword","GetIfTable","ptr", DllStructGetPtr($MIB_IFTABLE), "ulong*", DllStructGetSize($MIB_IFTABLE),"long",1)

    [/autoit] [autoit][/autoit] [autoit]

    ;Größe der Struktur und die Anzahl der Adapter speichern

    [/autoit] [autoit][/autoit] [autoit]

    Local $AdapterCount = DllStructGetData($MIB_IFTABLE, "dwNumEntries")
    Local $Pointer = DllStructGetPtr($MIB_IFTABLE, "puffer")

    [/autoit] [autoit][/autoit] [autoit]

    Local $MIB_IFROW = DllStructCreate($tagMIB_IFROW)
    $StructSize = DllStructGetSize($MIB_IFROW)
    Local $ReturnArray[$AdapterCount][24]
    For $i = 0 To $AdapterCount-1
    $MIB_IFROW = DllStructCreate($tagMIB_IFROW, $Pointer + $i*$StructSize)
    For $j = 0 To 23
    $ReturnArray[$i][$j] = DllStructGetData($MIB_IFROW, $j+1)
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $MIB_IFROW = 0
    $MIB_IFTABLE = 0

    [/autoit] [autoit][/autoit] [autoit]

    Return $ReturnArray
    EndFunc
    #include<Array.au3>
    $array = _GetNetUsage()
    ; Namen zur Info einfügen
    $Count = UBound($array,1)
    ReDim $array[$Count+1][UBound($array,2)]
    $array[$Count][0] = "wszName"
    $array[$Count][1] = "dwIndex"
    $array[$Count][2] = "dwType"
    $array[$Count][3] = "dwMtu"
    $array[$Count][4] = "dwSpeed"
    $array[$Count][5] = "dwPhysAddrLen"
    $array[$Count][6] = "bPhysAddr"
    $array[$Count][7] = "dwAdminStatus"
    $array[$Count][8] = "dwOperStatus"
    $array[$Count][9] = "dwLastChange"
    $array[$Count][10] = "dwInOctets"
    $array[$Count][11] = "dwInUcastPkts"
    $array[$Count][12] = "dwInNUcastPkts"
    $array[$Count][13] = "dwInDiscards"
    $array[$Count][14] = "dwInErrors"
    $array[$Count][15] = "dwInUnknownProtos"
    $array[$Count][16] = "dwOutOctets"
    $array[$Count][17] = "dwOutUcastPkts"
    $array[$Count][18] = "dwOutNUcastPkts"
    $array[$Count][19] = "dwOutDiscards"
    $array[$Count][20] = "dwOutErrors"
    $array[$Count][21] = "dwOutQLen"
    $array[$Count][22] = "dwDescrLen"
    $array[$Count][23] = "bDescr"

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay($array)

    [/autoit] [autoit][/autoit] [autoit]

    ; Beschreibungen der Schnittstellen ausgeben (bDescr ist ein ANSI-String)
    For $i = 0 To $Count-1
    MsgBox(0, '', BinaryToString(BinaryMid($array[$i][23],1,$array[$i][22])))
    Next

    [/autoit]
  • Klasse vielen Dank, hatte die Hoffnung schon fast aufgegeben das es möglich ist, auf der anderen Seite hab ich im englischen Forum einen Beitrag von dir gesehen wo du etwas ähnliches beschreibst (Hab ich allerdings auf Anhieb auch nicht verstanden :( )

    Eine kleine Verbesserung hab ich noch:

    aus "BYTE bDescr[" & $MAXLEN_IFDESCR & "];"
    "CHAR bDescr[" & $MAXLEN_IFDESCR & "];" dann stehen die Beschreibungen bereits richtig im Array.

    Werde es mir morgen nochmal in Ruhe ansehen und versuchen zu verstehen, ich glaub heute hab ich nicht mehr den Kopf frei dafür.
    Nochmal danke!

  • Ich hab die DLLStruct eben 1:1 von MSDN übernommen und danach ausgetestet, ob da lesbare Daten drin sind. deshalb ist das Byte und BinaryToString.