DllCall | api.dll von gta-api.de | SA:MP

  • Hallo Autoit3'ler!

    Ich bin an einer geraumen zeit an einem Keybinder für GTA San Andreas Multiplayer Mod (SA-MP.com) dran und bräuchte von euch Hilfe im Thema "DllCall"

    Damit ihr mein Problem versteht und auch nachvollziehen könnt erklär ich euch kurz warum ich dieses Problem habe:

    Damals wo ich ein Script mit einer anderen API.dll angefangen habe, gab es dazu auch gute beispiele in Autoit, jedoch ist es nun so das die API.dll von einem anderen Entwickler der den "betrieb" der .dll eingestellt hat, nun auch nicht mehr funktioniert. (Wegen Update's und Version Prüfungen innerhalb der dll)

    Das war / ist das alte script mit der Anderen API.dll:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

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

    $dll = DllOpen("API.dll")

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

    $hModule = DllCall($dll, "UINT", "LoadLibrary", "str", "API.dll")

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

    Global $tickets = 0

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

    Global $username = InputBox("Username","Target ( Username ) Eingeben!")
    Global $zeitinterval = InputBox("zeitinterval","Zeit in MS warten auf neue 'BEFEHLR': ")
    Global $sperre = InputBox("Sperre","Ab wieviel soll der keybinder aufhören ? ( Zahl eingabe ) ")
    Global $BinderAktiv = 0

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

    HotKeySet ( "+!c" , "KeyAktive" ) ;shift+alt+C
    HotKeySet ( "+!v" , "CloseProgramm" ) ;shift+alt+V

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

    #Region ### START Koda GUI section ### Form=D:\Source - Programme\Keybinder\Log.kxf
    $Log = GUICreate("~", 701, 326, 559, 367)
    GUISetBkColor(0xA0A0A4)
    $log_file = GUICtrlCreateEdit("", 8, 70, 685, 249, $ES_AUTOVSCROLL+$WS_VSCROLL)
    GUICtrlSetFont(-1, 12, 400, 0, "MS Sans Serif")
    GUICtrlSetColor(-1, 0x008000)
    GUICtrlSetBkColor(-1, 0x000000)
    $id_change = GUICtrlCreateButton("UserID Ändern", 388, 21, 111, 32)
    GUICtrlSetCursor (-1, 0)
    $intervalchange = GUICtrlCreateButton("Zeit Interval Ändern", 245, 21, 126, 32)
    GUICtrlSetCursor (-1, 0)

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

    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    CloseProgramm()
    Case $id_change
    $username = InputBox("Username","Ziel Benutzername ( Username ) Eingeben!")
    Case $intervalchange
    $zeitinterval = InputBox("$zeitinterval","Zeitspanne in ms")
    EndSwitch

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

    If $BinderAktiv == 1 Then

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

    $data = GetPlayerData()
    $PlayerID = GetPlayerIdByName($username)
    SendChat("/su " & $PlayerID & " 1 BV")
    SendChat("/arrest " & $PlayerID & " 1 10000")
    $tickets += 1
    $cashresult = $tickets * 5000
    WriteDebugLog(@HOUR & ":" & @MIN & ":" & @SEC & "- /su " & $PlayerID & " 1 BV | /arrest " & $PlayerID & " 1 10000 | Int: " & $zeitinterval & " | VERB: " & $tickets & " | CASH:" & $cashresult )
    Sleep($zeitinterval)
    If $tickets == $sperre Then
    $BinderAktiv = 0
    $cashresult = $tickets * 5000
    WriteDebugLog("Script gestoppt :: " & $tickets & " Vebrechen erreicht! ~ Cash result: " & $cashresult)
    AddChatMessage(0x00FFFF, "Script gestoppt :: " & $tickets & " Vebrechen erreicht! ~ Cash result: " & $cashresult)
    SoundPlay(@WindowsDir & "\media\tada.wav", 1)
    EndIf

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

    EndIf
    WEnd

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

    Func WriteDebugLog($Textt)
    GUICtrlSetData ($log_file, $Textt & @CRLF,1)
    EndFunc

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

    Func KeyAktive()
    If $BinderAktiv == 0 Then
    $BinderAktiv = 1
    $tickets = 0
    AddChatMessage(0x00FFFF, " ~~~~ Script Aktiviert ~~~~")
    WriteDebugLog(" ~~~~ Script Aktiviert ~~~~")
    Else
    $BinderAktiv = 0
    AddChatMessage(0xFFFF00, " ~~~~ Script Deaktiviert ~~~~")
    WriteDebugLog(" ~~~~ Script Deaktiviert ~~~~")
    $cashresult = $tickets*5000
    WriteDebugLog("Script abgrebrochen :: " & $tickets & " Vebrechen erreicht! ~ Cash result: " & $cashresult)
    AddChatMessage(0x00FFFF, "Script abgrebrochen :: " & $tickets & " Vebrechen erreicht! ~ Cash result: " & $cashresult)
    EndIf
    EndFunc

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

    Func CloseProgramm()
    DllClose($dll)
    Exit
    EndFunc

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

    ; API Functionen
    Func GetOnlinePlayers()
    $ret = DllCall($dll, "int:cdecl", _
    "API_GetOnlinePlayers")
    Return $ret[0]
    EndFunc

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

    Func GetPlayerIdByName($name)
    $ret = DllCall($dll, "int:cdecl", _
    "API_GetPlayerIdByName", _
    "str", $name)
    Return $ret[0]
    EndFunc

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

    Func GetPlayerPingByName($name)
    $ret = DllCall($dll, "int:cdecl", _
    "API_GetPlayerPingByName", _
    "str", $name)
    Return $ret[0]
    EndFunc

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

    Func GetPlayerData()
    $ret = DllCall($dll, "int:cdecl", _
    "API_GetPlayerData")
    Return $ret[0]
    EndFunc

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

    Func GetPlayerPing()
    $ret = DllCall($dll, "int:cdecl", _
    "API_GetPlayerPing")
    Return $ret[0]
    EndFunc

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

    Func AddChatMessage($Color, $Text)
    $ret = DllCall($dll, "int:cdecl", _
    "API_AddChatMessage", _
    "int", $Color, _
    "str", $Text)
    Return $ret[0]
    EndFunc

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

    Func SendChat($Text)
    $ret = DllCall($dll, "int:cdecl", _
    "API_SendChat", _
    "str", $Text)
    Return $ret[0]
    EndFunc

    [/autoit]

    Dieses Script hat auch wunderbar funktioniert.

    Nun gibt es die API von http://www.gta-api.de/ | Github: https://github.com/Slider1338/GTA-API
    Damit habe ich das problem die DLL Aufzurufen bzw Funktionen so aufrufen das sie funktionieren.
    Das ist mein Aktuelles Script in Autoit3:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <WinAPI.au3>
    #include <Misc.au3>
    #include <GuiButton.au3>
    #include <EditConstants.au3>
    #include <Array.au3>
    #include <GuiEdit.au3>

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

    OnAutoItExitRegister("OnAutoItExit")

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

    $dll = DllOpen("API.dll")
    $hModule = DllCall($dll, "UINT", "LoadLibrary", "str", "API.dll")

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

    $debug = GUICreate("debug", 598, 420, -1, -1)
    $log = GUICtrlCreateEdit("", 0, 0, 598, 420, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY), 0)
    GUISetState(@SW_SHOW)

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

    AdlibRegister("CheckData", 1500)

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    WEnd

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

    Func CheckData()
    WriteToLog("ServerName: " & GetServerName())
    EndFunc

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

    Func WriteToLog($str)
    _GUICtrlEdit_InsertText($log, $str & @CRLF)
    EndFunc;==>WriteToLog($str)

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

    Func GetServerName()
    $ret = DllCall($dll, "int:cdecl", _
    "GetServerName")
    Return $ret[0]
    EndFunc;==>GetServerName()

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

    Func OnAutoItExit()
    $logFile = @ScriptDir & '\log.txt'
    FileOpen($logFile)
    FileWrite($logFile, GUICtrlRead($log))
    FileClose($logFile)
    EndFunc;==>OnAutoItExit()

    [/autoit]

    Für diese API von gta-api.de gibt es aktuell nur Beispiele in AutoHotkey (siehe github oder gta-api.de)

    Meine fragen lauten also,
    Wie kann ich die DLL Aufrufen so das sie auch "geladen" wird?
    Wie kann ich die DLL Funktionen aufrufen? da meine Aktuelle GetServerName Funktion nur eine 0 ausgibt:

    [autoit]


    Func GetServerName()
    $ret = DllCall($hModule, "int:cdecl", _
    "GetServerName")
    Return $ret
    EndFunc;==>GetServerName()

    [/autoit]


    Unter anderem verstehe ich DllCall allgemein mäßig leider nicht
    ich weiß das ich mit

    [autoit]

    DllCall ( "dll", "return type", "function" [, type1, param1 [, type n, param n]] )

    [/autoit]


    Mit der DLL kommunizieren kann, jedoch weiß ich nicht wie man auf den return type : int:cdecl kommt.
    str = string? oder nicht?

    Ich bedanke mich ganz herzlich schon mal im Voraus!!

    LG, Florian.

  • Du sagst, ja das du eine vollständig neue .DLL eines anderen Entwicklers nutzt. Trotzdem verwendest du einen Begriff, der vermutlich für die alte .dll gillt:

    [autoit]

    $hModule = DllCall($dll, "UINT", "LoadLibrary", "str", "API.dll")

    [/autoit]

    Ich denke dieser Befehl ist eine Funktion der alten .dll und somit nicht kompatibel.


    Ich glaube du musst direkt mit DllCall deine Funktion ausführen...
    z.B.

    [autoit]

    Local $hDLL = DllOpen("API.dll")

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

    Local $aResult = DllCall($hDLL,"int:cdecl","GetServerName")
    msgbox (0,"",$aResult )
    DllClose($hDLL)

    [/autoit]

    Aber ich bin da auch nicht der Fachmann...

    Einmal editiert, zuletzt von KloMeister (30. Januar 2015 um 19:23)

  • Sorry hatte (Weil ich den Code aus nem AutoIt Beispiel hatte) da noch User32.dll drin stehen, habs in API.dll geändert (Hoffe das hast du gemerkt und schon vorher geändert)... Denn ansonsten ist der Absturz relativ klar

    Kannst ja auch mal versuchen statt "GetServerName" einen anderen API Befehl zu nehmen. Das Problem ist bei "GetServerName", handelt es sich ja vermutlich um einen String und nicht um einen Integer.


    Kann aber auch sein, das mein Aufbau des Befehls grundsätzlich nicht 100% korrekt ist, ich kenne mich mit dem Aufruf von DLL Funktionen nicht wirklich aus... Testen kann ich das ganze leider auch nicht, weil ich GTA dafür brauche.

    2 Mal editiert, zuletzt von KloMeister (30. Januar 2015 um 19:34)

  • Ja das habe ich gemerkt. Ich habe mit dem gedanken gespielt und auch schon getestet ob ich die Memory's adressen einfach selbst abfrage, die Adressen sind ja im Source Code enthalten und auch auf verschiedenen Webseiten.

    Dazu hab ich folgendes Script direkt angepasst:

    Spoiler anzeigen
    [autoit]

    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <WinAPI.au3>
    #include <Misc.au3>
    #include <GuiButton.au3>
    #include <EditConstants.au3>
    #include <Array.au3>
    #include <GuiEdit.au3>
    #include "NomadMemory.au3"

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

    OnAutoItExitRegister("OnAutoItExit")

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

    Local $GTA_Run = ProcessExists("gta_sa.exe")

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

    If ProcessExists("gta_sa.exe") Then
    MsgBox(0, "GTA Run?", $GTA_Run)
    EndIf

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

    ; GTA SA
    $GTA_CPED_POINTER_ADDR = 0xB6F5F0
    $GTA_PLAYER_MONEY = 0xB7CE50
    $GTA_PLAYER_HEALTH_ADDR = 0x540
    $GTA_PLAYER_ARMOUR_ADDR = 0x548
    $GTA_PLAYER_POS_X = 0xB6F2E4
    $GTA_PLAYER_POS_Y = 0xB6F2E8
    $GTA_PLAYER_POS_Z = 0xB6F2EC
    $GTA_PLAYER_INTERIOR_ADDR = 0xA4ACE8
    $GTA_PLAYER_WEAPONID_ADDR = 0x740
    $GTA_PLAYER_WEAPON_SLOT_ADDR = 0xB7CDBC
    $GTA_PLAYER_WEAPON_CLIP_AMMO_ADDR = 0x1207F0
    $GTA_VEHICLE_POINTER_ADDR = 0xBA18FC
    $GTA_VEHICLE_HEALTH_ADDR = 0x4C0
    $GTA_VEHICLE_SIREN_STATE_ADDR = 0x42D
    $GTA_PLAYERSTATE_INCAR_ADDR = 0x530
    $GTA_VEHICLE_DOORSTATE_ADDR = 0x4F8
    $GTA_VEHICLE_ENGINESTATE_ADDR = 0x428
    $GTA_VEHICLE_LIGHTSTATE_ADDR = 0x584
    $GTA_VEHICLE_TYPE_ADDR = 0x590
    $GTA_VEHICLE_MODEL_ADDR = 0x22

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

    ; SAMP
    $MAX_PLAYERS = 1000
    $AUTO_SCOREBOARD_REFRESH = 10000
    $MAX_PLAYER_NAME = 30
    $MAX_SERVERNAME_LENGTH = 50

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

    $SAMP_SERVERIP_ADDR = 0x2121F5
    $SAMP_PLAYERSONLINE_OFFSET = 0x4
    $SAMP_PLAYERSONLINE_ADDR = 0x212A3C
    $SAMP_PLAYERNAME_ADDR = 0x21242F
    $SAMP_SENDCHAT_FUNC_ADDR = 0x4C30
    $SAMP_SENDCMD_FUNC_ADDR = 0x63390
    $SAMP_PLAYERID_OFFSET = 0x4
    $SAMP_PLAYERSCORE_OFFSET = 0x2A
    $SAMP_PLAYERPING_OFFSET = 0x26
    $SAMP_SCOREBOARD_OFFSET = 0x7D10
    $SAMP_SCOREBOARD_PLAYERPOOLS_OFFSET = 0x3D9
    $SAMP_SCOREBOARD_PLAYERPOOL_OFFSET = 0x14
    $SAMP_SCOREBOARD_PLAYER_OFFSET = 0x2E
    $SAMP_SCOREBOARD_PLAYER_NAME_OFFSET = 0x14
    $SAMP_SCOREBOARD_PLAYER_NAMELNG_OFFSET = 0x24
    $SAMP_SCOREBOARD_PLAYER_SCORE_OFFSET = 0x4
    $SAMP_SCOREBOARD_PLAYER_PING_OFFSET = 0xC
    $SAMP_ISINCHAT_ADDR = 0x212ACC
    $SAMP_ISINCHAT_OFFSET = 0x55
    $SAMP_SERVERNAME_ADDR = 0x212AB8
    $SAMP_SERVERNAME_OFFSET = 0x2C6
    $SAMP_DIALOG_OBJECT = 0x212A78
    $SAMP_CHATINFO_OBJECT = 0x212AA4
    $SAMP_ADDCHATMESSAGE_FUNC_ADDR = 0x61FC0

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

    $debug = GUICreate("debug", 598, 420, -1, -1)
    $log = GUICtrlCreateEdit("", 0, 0, 598, 420, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY), 0)
    GUISetState(@SW_SHOW)
    AdlibRegister("CheckData", 1500)

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    WEnd

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

    Func CheckData()
    WriteToLog("GetServerName: " & GetServerName())
    EndFunc

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

    Func WriteToLog($str)
    _GUICtrlEdit_InsertText($log, $str & @CRLF)
    EndFunc;==>WriteToLog($str)

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

    Func GetServerName()
    $memOpen = _MemoryOpen($GTA_Run)
    $read = _MemoryRead($SAMP_SERVERNAME_ADDR + $SAMP_SERVERNAME_OFFSET, $memOpen)
    return $read
    EndFunc;==>GetServerName()

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

    Func OnAutoItExit()
    $logFile = @ScriptDir & '\log.txt'
    FileOpen($logFile)
    FileWrite($logFile, GUICtrlRead($log))
    FileClose($logFile)
    EndFunc;==>OnAutoItExit()

    [/autoit]

    Und Siehe da -> Servername gibt 0 aus :D
    Also sind die Memory Adressen von der .dll Falsch oder ich mach das mit der Memory Abfrage falsch

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

    Func GetServerName()
    $memOpen = _MemoryOpen($GTA_Run)
    $read = _MemoryRead($SAMP_SERVERNAME_ADDR + $SAMP_SERVERNAME_OFFSET, $memOpen)
    return $read
    EndFunc;==>GetServerName()

    [/autoit]
  • Ich kann dir folgenden Beispiel-Code zum auslesen des Prozessspeichers anbieten, welcher so auch 100% funktioniert:

    [autoit]


    #include <WinAPI.au3>
    #include <MsgBoxConstants.au3>
    #include <Constants.au3>

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

    Global $Process="Winamp.exe";Ersetze mit deinem Prozess
    Global $Pointer = 0x004B5E54; Ersetze mit deiner Adresse
    $handle=_WinAPI_OpenProcess(BitOR($PROCESS_VM_OPERATION,$PROCESS_VM_READ),False,ProcessExists($Process))
    $s=DllStructCreate("int")
    Local $read
    _WinAPI_ReadProcessMemory($handle,$Pointer,DllStructGetPtr($s),DllStructGetSize($s),$read)
    MsgBox(0,"Gelesener Wert",DllStructGetData($s,1))

    [/autoit]

    Aktuell ließt die Funktion die aktuelle Trackzeit aus Winamp aus.

    Wenn du den Prozess in GTA und die Speicher-Adresse in einen deiner Werte änderst, kannst du das ganze auch mal mit GTA testen. Sollte dann immernoch 0 zurückkommen, ist vermutlich wirklich etwas verkehrt.

    Wenn Spiele gepatched werden, kann es durchaus zu einer Verschiebung bestimmte Speicheradressen kommen.


    Was natürlich auch noch sein kann: Manche Anwendungen benötigen besondere Rechte zum Auslesen des Prozesspeichers. Um daran zu kommen muss man sich erst die Rechte freischalten mit ein paar Api Befehlen...
    Dazu habe ich keinen AutoIt Code, in VB6 ging das so:

    Spoiler anzeigen
  • Viele dank!!

    Da der servername immer noch eine 0 ausgibt, geh ich davon aus das die adressen falsch sind.
    Bin gerade auch schon dabei mit CheatEngine mir die Adressen selbst raus zu suchen.

    Eine wichtige frage hätte ich da noch,

    Kann ich bei

    [autoit]

    $s = DllStructCreate("char[128]"); //edit

    [/autoit]


    wenn es sich um einen String handelt, 'string' schreiben oder 'str'?
    oder muss das wieder was ganz anderes sein?

    Lg

    // edit: habs gefunden, musste char[128] reinschreiben.. Danke für deine Hilfe!!

    2 Mal editiert, zuletzt von C0nc1l (31. Januar 2015 um 17:12)