#include-once
;#####################################################################
;#
;# Funtion _GetCPUUsage()
;# Ermittelt die Auslastung der CPU, Multicore Kompatibel
;#
;# Rückgabewert:	Array
;#					Array[0] Anzahl der CPUs, Fehler wenn negativ
;#					Array[n] Auslastung der n-ten CPU in Prozent
;#
;#		Fehler:		-1 Fehler beim 1. Dll Aufruf
;#					-2 Fehler beim 2. Dll Aufruf
;#					-3 Fehler beim 3. Dll Aufruf
;#
;# Autor: Bitboy
;#####################################################################
Func _GetCPUUsage()
	Local Const $SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = 8
	Local Const $SYSTEM_TIME_INFO = 3
	Local Const $tagS_SPPI = "int64 IdleTime;int64 KernelTime;int64 UserTime;int64 DpcTime;int64 InterruptTime;long InterruptCount"

	Local $CpuNum, $IdleOldArr[1], $IdleNewArr[1], $tmpStruct
	Local $timediff = 0, $starttime = 0
	Local $S_SYSTEM_TIME_INFORMATION, $S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
	Local $RetArr[1]

	Local $S_SYSTEM_INFO = DllStructCreate("ushort dwOemId;short wProcessorArchitecture;dword dwPageSize;ptr lpMinimumApplicationAddress;" & _
			"ptr lpMaximumApplicationAddress;long_ptr dwActiveProcessorMask;dword dwNumberOfProcessors;dword dwProcessorType;dword dwAllocationGranularity;" & _
			"short wProcessorLevel;short wProcessorRevision")

	;Anzahl der CPUs bestimmen
	$err = DllCall("Kernel32.dll", "none", "GetSystemInfo", "ptr", DllStructGetPtr($S_SYSTEM_INFO))

	If @error Or Not IsArray($err) Then ;Fehler beim 1. Dll Aufruf
		Return $RetArr[0] = -1
	Else
		$CpuNum = DllStructGetData($S_SYSTEM_INFO, "dwNumberOfProcessors")
		ReDim $RetArr[$CpuNum + 1]
		$RetArr[0] = $CpuNum
	EndIf
	$S_SYSTEM_INFO = 0

	While 1
		;Erstellen der Struktur für die Prozessor Performance
		$S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = DllStructCreate($tagS_SPPI)
		;Größe Struktur um später vielfache (MultiCore) der Structur lesen zu können
		$StructSize = DllStructGetSize($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)
		;Erstellen einer Pufferstruktur
		$S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = DllStructCreate("byte puffer[" & $StructSize * $CpuNum & "]")
		;Pointer zum wiederfinden
		$pointer = DllStructGetPtr($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)

		$err = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", _
				"int", $SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, _
				"ptr", DllStructGetPtr($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), _
				"int", DllStructGetSize($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), _
				"int", 0)

		;Fehler beim 2. Dll Aufruf
		If $err[0] Then
			Return $RetArr[0] = -2
		EndIf

		;Struktur und Dll-Aufruf für Zeitmessung
		Local $S_SYSTEM_TIME_INFORMATION = DllStructCreate("int64;int64;int64;uint;int")
		$err = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", _
				"int", $SYSTEM_TIME_INFO, _
				"ptr", DllStructGetPtr($S_SYSTEM_TIME_INFORMATION), _
				"int", DllStructGetSize($S_SYSTEM_TIME_INFORMATION), _
				"int", 0)

		;Fehler beim 3. Dll Aufruf
		If $err[0] Then
			Return $RetArr[0] = -3
		EndIf

		If $starttime = 0 Then ;Startwerte Ermitteln
			ReDim $IdleOldArr[$CpuNum]
			;Start-Informationen Auslesen
			For $i = 0 To $CpuNum - 1
				$tmpStruct = DllStructCreate($tagS_SPPI, $pointer + $i * $StructSize)
				$IdleOldArr[$i] = DllStructGetData($tmpStruct, "IdleTime")
			Next
			;Startzeit ermitteln
			$starttime = DllStructGetData($S_SYSTEM_TIME_INFORMATION, 2)
			;Verzögerung um einen Zeitunterschied sicher zu stellen
			Sleep(100)
		Else
			ReDim $IdleNewArr[$CpuNum]
			;Neue Informationen auslesen
			For $i = 0 To $CpuNum - 1
				$tmpStruct = DllStructCreate($tagS_SPPI, $pointer + $i * $StructSize)
				$IdleNewArr[$i] = DllStructGetData($tmpStruct, "IdleTime")
			Next

			;Zeitdifferenze in 100 nanosekunden
			$timediff = DllStructGetData($S_SYSTEM_TIME_INFORMATION, 2) - $starttime

			;Auslastung errechnen
			For $i = 0 To $CpuNum - 1
				$RetArr[$i + 1] = Round(100 - (($IdleNewArr[$i] - $IdleOldArr[$i]) * 100 / $timediff))
			Next

			Return $RetArr
		EndIf

		;Speicher wieder frei geben
		$S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = 0
		$S_SYSTEM_TIME_INFORMATION = 0
		$tmpStruct = 0
	WEnd
EndFunc   ;==>_GetCPUUsage

;#####################################################################
;#
;# Funtion _GetCPUUsageOld()
;# Ermittelt die Auslastung der CPU (Wie im Taskmanager angezeigt)
;#
;# Rückgabewert:	Auslastung der CPU in Prozent, Fehler wenn negativ
;#		Fehler:		-1 Fehler beim 1. Dll Aufruf
;#					-2 Fehler beim 2. Dll Aufruf
;#					-3 Fehler beim 3. Dll Aufruf
;#
;# Hinweis: Mit zukünftigen Windowsversion eventuell nicht kompatibel,
;#			Ungenau bei Multi-Prozessorsystemen
;#
;# Autor: ???
;#####################################################################
Func _GetCPUUsageOld()
	Local Const $SYSTEM_BASIC_INFO = 0
	Local Const $SYSTEM_PERFORMANCE_INFO = 2
	Local Const $SYSTEM_TIME_INFO = 3

	Local $idletimeold = 0, $idletimediff = 0, $idle
	Local $starttime = 0, $timediff = 0, $CPUCount = 0

	;Struktur für Basis Informationen
	$S_SYSTEM_BASIC_INFORMATION = DllStructCreate("int;uint;uint;uint;uint;uint;uint;ptr;ptr;uint;byte;byte;short")
	$err = DllCall("ntdll.dll", _
			"int", "NtQuerySystemInformation", _
			"int", $SYSTEM_BASIC_INFO, _
			"ptr", DllStructGetPtr($S_SYSTEM_BASIC_INFORMATION), _
			"int", DllStructGetSize($S_SYSTEM_BASIC_INFORMATION), _
			"int", 0)

	If $err[0] Then Return -1

	$CPUCount = DllStructGetData($S_SYSTEM_BASIC_INFORMATION, 11)
	$S_SYSTEM_BASIC_INFORMATION = 0

	While 1
		;Struktur für CPU Zeit
		Local $S_SYSTEM_PERFORMANCE_INFORMATION = DllStructCreate("int64;int[76]")
		$err = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", "int", $SYSTEM_PERFORMANCE_INFO, _
				"ptr", DllStructGetPtr($S_SYSTEM_PERFORMANCE_INFORMATION), _
				"int", DllStructGetSize($S_SYSTEM_PERFORMANCE_INFORMATION), _
				"int", 0)
		If $err[0] Then Return -2

		;Struktur für Zeitmessung
		Local $S_SYSTEM_TIME_INFORMATION = DllStructCreate("int64;int64;int64;uint;int")
		$err = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", _
				"int", $SYSTEM_TIME_INFO, _
				"ptr", DllStructGetPtr($S_SYSTEM_TIME_INFORMATION), _
				"int", DllStructGetSize($S_SYSTEM_TIME_INFORMATION), _
				"int", 0)

		If $err[0] Then Return -3

		;Startwerte ermitteln
		If $starttime = 0 Then
			$idletimeold = DllStructGetData($S_SYSTEM_PERFORMANCE_INFORMATION, 1)
			$starttime = DllStructGetData($S_SYSTEM_TIME_INFORMATION, 2)
			Sleep(100)
		Else
			; "Aktuelle" Werte ermitteln
			$idletimediff = DllStructGetData($S_SYSTEM_PERFORMANCE_INFORMATION, 1) - $idletimeold
			$timediff = DllStructGetData($S_SYSTEM_TIME_INFORMATION, 2) - $starttime

			;Berechnung
			$idle = Round(100.0 - ($idletimediff * 100.0 / $timediff) / $CPUCount, 0)
			Return $idle
		EndIf
		$S_SYSTEM_PERFORMANCE_INFORMATION = 0
		$S_SYSTEM_TIME_INFORMATION = 0
	WEnd
EndFunc   ;==>_GetCPUUsageOld

;####################################################
;#
;# Funtion _GetMemUsage()
;# Ermittelt die Ram-Auslastung in Prozent
;#
;# Rückgabewert: Array 	[0] Physikalischer Speicher
;#						[1] Auslagerungsdatei
;#						[2] Virtueller Speicher
;#
;# Autor: Bitboy
;####################################################
Func _GetMemUsage()
	Local $memstat, $RetArr[3]
	$memstat = MemGetStats()

	$RetArr[0] = $memstat[0] ;Physikalischer Speicher
	$RetArr[1] = Round(100 - ($memstat[4] / $memstat[3] * 100)) ;Auslagerungsdatei
	$RetArr[2] = Round(100 - ($memstat[6] / $memstat[5] * 100)) ;Virtueller Speicher

	Return $RetArr
EndFunc   ;==>_GetMemUsage

;####################################################
;#
;# Funtion _GetNetUsage()
;# Ermittelt die Auslastung aller _Ethernet_ Adapter
;#
;# Rückgabewert: Array 	[n][0] Name des Adapters
;#						[n][1] Auslastung in Prozent
;#
;# Autor: Bitboy
;####################################################
Func _GetNetUsage()
	Local $netarrold[1], $netarr[1], $tmparr, $RetArr[1]
	Local $AdapterNum, $i, $x, $timediff, $netcounter = 0, $InOutBytes

	For $i = 1 To 2
		$tmparr = _GetNetAdapterInfo($AdapterNum)
		If $i = 1 Then
			ReDim $netarrold[$AdapterNum][2]
			$timediff = TimerInit()
			For $x = 0 To $AdapterNum - 1
				If $tmparr[$x][2] = 6 Then ;Ethernet Adapter
					;InOctets
					$netarrold[$netcounter][0] = $tmparr[$x][10]
					;OutOctets
					$netarrold[$netcounter][1] = $tmparr[$x][16]
					$netcounter = $netcounter + 1
				EndIf
			Next
			Sleep(100)
		Else
			$timediff = TimerDiff($timediff)
			ReDim $RetArr[$netcounter][2]
			$netcounter = 0
			For $x = 0 To $AdapterNum - 1
				If $tmparr[$x][2] = 6 Then ;Ethernet Adapter
					;Adapternamen speichern
					$RetArr[$netcounter][0] = $tmparr[$x][23]
					;Auslastung = ((InOctets + Outoctets) - (InOctetsOld + OutoctetsOld) / timediff/1000) / Netspeed * 8 * 100
					$InOutBytes = ($tmparr[$x][10] + $tmparr[$x][16]) - ($netarrold[$netcounter][0] + $netarrold[$netcounter][1])
					$RetArr[$netcounter][1] = Round(($InOutBytes / ($timediff / 1000)) / $tmparr[$x][4] * 8 * 100)
					$netcounter = $netcounter + 1
				EndIf
			Next
			Return $RetArr
		EndIf
	Next
EndFunc   ;==>_GetNetUsage

;################################################################################################################
;#
;# Funktion _GetNetAdapterInfo (ByRef $AdapterNum)
;# Interne Funktion zum Ermitteln von Netzwerkadapter Informationen
;#
;# Rückgabewerte:	Array [n][0] wszName, meist (immer?) leer
;#					Array [n][1] dwIndex, Indexnummer des Adapters
;#					Array [n][2] dwType, Typ des Adapters, Siehe Konstanten
;#					Array [n][3] dwMTU, Maximale Paketgröße
;#					Array [n][4] dwSpeed, Geschwindigkeit in Bit/Sekunde
;#					Array [n][5] dwPhysAddrLen, Länge der Physikalischen (MAC) Adresse (Immer 8)
;#					Array [n][6] bPhysAddr, Physikalische (MAC) Adresse
;#					Array [n][7] dwAdminStatus, Verbindung  aktiviert? 1 oder 0
;#					Array [n][8] dwOperStatus,???
;#					Array [n][9] dwLastChange, Letzte Veränderung seit Systemstart in hunderstel-sekunden
;#					Array [n][10] dwInOctets, Empfangene Oktetts (1 Oktett = 8 Bit = 1 Byte)
;#					Array [n][11] dwInUcastPkts, Empfangene Unicast Pakete
;#					Array [n][12] dwInNUcastPkts, Empfangene Non-Unicast Pakete
;#					Array [n][13] dwInDiscards, Empfangene und verworfene Pakete
;#					Array [n][14] dwInErrors, Empfangene und verworfene fehlerhafte Pakete
;#					Array [n][15] dwInUnknownProtos, Empfangene und verworfene Pakete wegen unbekanntem Protokoll
;#					Array [n][16] dwOutOctets, Gesendete Oktetts (1 Oktett = 8 Bit = 1 Byte)
;#					Array [n][17] dwOutUcastPkts, Gesendete Unicast Pakete
;#					Array [n][18] dwOutNUcastPkts, Gesendete Non-Unicast Pakete
;#					Array [n][19] dwOutDiscards, Gesendete und verworfene Pakete
;#					Array [n][20] dwOutErrors, Gesendete und verworfene fehlerhafte Pakete
;#					Array [n][21] dwOutQLen, Übertragungswarteschlange (derzeit unbenutzt)
;#					Array [n][22] dwDescrLen, Zeichenlänge des Adapternamens (Konstant 256)
;#					Array [n][23] bDescr, Adaptername
;#					$AdapterNum enthält die Anzahl der Adapter [n]
;#
;# Autor: Progandy (autoit.de), Bitboy
;################################################################################################################
Func _GetNetAdapterInfo(ByRef $AdapterNum)
	;Konstantendeklaration
	;Netzwerk Adapter Typen
	Local Const $MIB_IF_TYPE_OTHER = 1 ;Some other type of network interface.
	Local Const $MIB_IF_TYPE_ETHERNET = 6 ;An Ethernet network interface.
	Local Const $MIB_IF_TYPE_TOKENRING = 9 ;A token ring network interface.
	Local Const $MIB_IF_TYPE_PPP = 23 ;A PPP network interface.
	Local Const $MIB_IF_TYPE_LOOPBACK = 24 ;A software loopback network interface.
	Local Const $MIB_IF_TYPE_ATM = 37 ;An ATM network interface.
	Local Const $MIB_IF_TYPE_IEEE80211 = 73 ;An IEEE 802.11 wireless network interface.
	Local Const $MIB_IF_TYPE_TUNNEL = 131 ;A tunnel type encapsulation network interface.
	Local Const $MIB_IF_TYPE_IEEE1394 = 144 ;An IEEE 1394 (Firewire) high performance serial bus network interface.

	Local Const $MAX_INTERFACE_NAME_LEN = 256
	Local Const $MAXLEN_IFDESCR = 256
	Local Const $MAXLEN_PHYSADDR = 8

	;Struktur für Tabellenzeile
	Local 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;" & _
			"CHAR  bDescr[" & $MAXLEN_IFDESCR & "];"

	;Deklaration der Struktur MIB_IFTABLE
	Local Const $tagMIB_IFTABLE_HEADER = "DWORD dwNumEntries;"

	;Variablendeklaration
	Local $puffersize = 0, $StructSize = 0, $i = 0, $j = 0, $AdapterCount = 0
	Local $puffer, $pointer, $RetArr[1][1]
	Local $MIB_IFROW = DllStructCreate($tagMIB_IFROW)

	;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

	;Erstellen der Struktur MIB_IFTABLE mit passender Puffergröße
	Local $MIB_IFTABLE = DllStructCreate($tagMIB_IFTABLE_HEADER & "byte puffer[" & $puffersize & "]")

	;Zweiter Aufruf
	$err = DllCall("Iphlpapi.dll", "dword", "GetIfTable", "ptr", DllStructGetPtr($MIB_IFTABLE), "ulong*", DllStructGetSize($MIB_IFTABLE), "long", 1)

	;Größe der Struktur und die Anzahl der Adapter speichern
	$AdapterCount = DllStructGetData($MIB_IFTABLE, "dwNumEntries")
	$AdapterNum = $AdapterCount
	$StructSize = DllStructGetSize($MIB_IFROW)

	$pointer = DllStructGetPtr($MIB_IFTABLE, "puffer")
	ReDim $RetArr[$AdapterCount][24]
	For $i = 0 To $AdapterCount - 1
		$MIB_IFROW = DllStructCreate($tagMIB_IFROW, $pointer + $i * $StructSize)
		For $j = 0 To 23
			If $j = 6 Then
				$RetArr[$i][$j] = StringMid(DllStructGetData($MIB_IFROW, $j + 1), 3, 12)
			Else
				$RetArr[$i][$j] = DllStructGetData($MIB_IFROW, $j + 1)
			EndIf
		Next
	Next

	$MIB_IFROW = 0
	$MIB_IFTABLE = 0

	Return $RetArr
EndFunc   ;==>_GetNetAdapterInfo


#cs
	;Folgender Code dient nur zum Testen und kann gelöscht werden

	#include<Array.au3>
	Local $Count

	;CPU-Auslastung
	$test = _GetCPUUsage()
	_ArrayDisplay ($test)

	;Alte CPU-Auslastung
	MsgBox(0,"CPU Auslastung", _GetCPUUsageOld()&"%")

	;Ram-Auslastung
	$array = _GetMemUsage()
	_ArrayDisplay($array)

	;Netzwerkauslastung
	$array = _GetNetUsage()
	_ArrayDisplay($array)

	;Netwerkinfo
	$array = _GetNetAdapterInfo($Count)
	; Namen zur Info einfügen
	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"

	_ArrayDisplay($array)

#ce
