DLLCall etc.

  • Hallo zusammen,

    Wie ich nun leider merken musste, komme ich um das Thema DLL nichtmehr drum rum. Bis jetzt hab ich´s ja immer geschafft ^^.
    Leider bin ich da zu blöd für um es alleine zu schaffen, wie ich merken musste. Da das ganze nur ein Hobby ist und ich auch nicht aus der Programmierung komme, durfte ich feststellen das ich das was in der MSDN steht nicht wirklich verstehe!

    Kann mir bitte einer erklären wie ich anhand dieser Information: GlobalMemoryStatuEx die benötigten Informationen bekomme um einen DLLCall zu basteln.
    Ich brauch da definitiv mal ein Beispiel, vielleicht machts dann ja mal klick bei mir.

    Gruß
    MrB

    Einmal editiert, zuletzt von MrB (30. November 2013 um 20:01)

  • Einfach die wichtigen Infos rauslesen:

    Dann schauen wir uns noch an, was ein LPFILETIME ist. Der Name deutet auf einen Pointer zu einer FILETIME-Struktur hin (lp).
    Mal in der Beschreibung nachschauen, und tatsächlich:

    Zitat von MSDN


    A pointer to a FILETIME structure that receives the amount of time that the system has been idle.

    Also schauen wir uns noch an, wie die FILETIME-Struktur aufgebaut ist:

    Code
    typedef struct _FILETIME {
      DWORD dwLowDateTime;
      DWORD dwHighDateTime;
    } FILETIME, *PFILETIME;

    In AutoIt sieht die Struktur so aus:

    [autoit]


    Global $tagFILETIME = "dword dwLowDateTime; dword dwHighDateTime"

    [/autoit]

    Und mit ein bisschen Basteln/in Funktion bringen...

    Spoiler anzeigen
    [autoit]


    Global $tagFILETIME = "dword dwLowDateTime; dword dwHighDateTime"
    Global Enum $TIME_IDLE, $TIME_KERNEL, $TIME_USER
    Global Enum $TIME_LOWDATE, $TIME_HIGHDATE

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

    ;return as array
    Func _WinAPI_GetSystemTimes($iTimer)
    ;chesstiger
    $tIdleTime = DllStructCreate($tagFILETIME) ;IdleTime-Struct erstellen
    $tKernelTime = DllStructCreate($tagFILETIME) ;KernelTime-Struct erstellen
    $tUserTime = DllStructCreate($tagFILETIME) ;UserTime-Struct erstellen

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

    ;Pointer holen
    $pIdleTime = DllStructGetPtr($tIdleTime)
    $pKernelTime = DllStructGetPtr($tKernelTime)
    $pUserTime = DllStructGetPtr($tUserTime)

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

    ;DllCall:
    $hKernel32 = DllOpen("Kernel32.dll")
    DllCall($hKernel32, "boolean", "GetSystemTimes", "ptr", $pIdleTime, "ptr", $pKernelTime, "ptr", $pUserTime) ;Da wir ein lp... übergeben sollen: Pointer (ptr)
    ;Jetzt sind unsere Strukturen gefüllt
    ;Ein bisschen Schönheitsarbeit...
    Local $aiReturn[2]
    Switch $iTimer
    Case $TIME_IDLE
    $aiReturn[$TIME_LOWDATE] = DllStructGetData($tIdleTime, "dwLowDateTime")
    $aiReturn[$TIME_HIGHDATE] = DllStructGetData($tIdleTime, "dwHighDateTime")
    Case $TIME_KERNEL
    $aiReturn[$TIME_LOWDATE] = DllStructGetData($tKernelTime, "dwLowDateTime")
    $aiReturn[$TIME_HIGHDATE] = DllStructGetData($tKernelTime, "dwHighDateTime")
    Case $TIME_USER
    $aiReturn[$TIME_LOWDATE] = DllStructGetData($tUserTime, "dwLowDateTime")
    $aiReturn[$TIME_HIGHDATE] = DllStructGetData($tUserTime, "dwHighDateTime")
    EndSwitch

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

    ;und return!
    Return $aiReturn
    EndFunc

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

    ;Beispiel:
    $aUserTime = _WinAPI_GetSystemTimes($TIME_USER)
    MsgBox(0, "UserTime", "LowDate: " & $aUserTime[$TIME_LOWDATE] & @CRLF & "HighDate: " & $aUserTime[$TIME_HIGHDATE])

    [/autoit]

    Lg

  • chesstiger

    Big THX. Genau diese Anleitungen für Unwissende brauch ich ;)
    Mit den Beispielen komm ich klar und fange auch langsam an die ganze Sache zu verstehen.

    Also frisch ans Werk, wenigstens so lange bis ich wieder stecken bleibe ^^

    THX

    P.S.: Welchem Datentyp entspricht DWORDLONG in Autoit ?? uint64 ??

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

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

    $tagMemoryStatusEx = "dword dwLength; dword dwMemoryLoad; uint64 ullTotalPhys; uint64 ullAvailPhys; uint64 ullTotalPageFile; uint64 ullAvailPageFile; uint64 ullTotalVirtual; uint64 ullAvailVirtual; uint64 ullAvailExtendedVirtual"

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

    $tBuffer = DllStructCreate($tagMemoryStatusEx)

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

    $pBuffer = DllStructGetPtr($tBuffer)

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

    $hKernel32 = DllOpen("kernel32.dll")

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

    DllCall($hKernel32, "boolean", "GlobalMemoryStatusEx", "ptr", $pBuffer)

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

    Local $aiReturn[2]

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

    $aiReturn[0] = DllStructGetData($tBuffer, "dwLength")
    $aiReturn[1] = DllStructGetData($tBuffer, "dwMemoryLoad")

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

    _ArrayDisplay($aiReturn)

    [/autoit]

    Schlagt mich, aber ich finde den Fehler nicht! Bitte um Korrektur!

    4 Mal editiert, zuletzt von MrB (28. November 2013 um 20:55)

  • Hi,
    allererste Aktion nach dem Aufrufen einer Funktion ist zu prüfen, ob die Funktion überhaupt Erfolg zurückgemeldet hat!
    Das sollte in jeder Programmiersprache mit jeder Funktion machbar sein und gilt insbesondere für DllCalls!

    Bei deinem DllCall() bekommt man als Ergebnis 0, MSDN sagt dazu

    Zitat

    If the function succeeds, the return value is nonzero.

    Aha...die Frage ist, wieso.

    Aber wie meistens gilt der Spruch: "Wer lesen kann, ist klar im Vorteil" :D

    MSDN sagt weiterhin bei der MEMORYSTATUSEX structure

    Zitat

    dwLength
    The size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx.


    Aha, "set this member"...also machen wir das mal^^

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

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

    $tagMemoryStatusEx = "dword dwLength;" & _
    "dword dwMemoryLoad;" & _
    "uint64 ullTotalPhys;" & _
    "uint64 ullAvailPhys;" & _
    "uint64 ullTotalPageFile;" & _
    "uint64 ullAvailPageFile;" & _
    "uint64 ullTotalVirtual;" & _
    "uint64 ullAvailVirtual;" & _
    "uint64 ullAvailExtendedVirtual"

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

    $tBuffer = DllStructCreate($tagMemoryStatusEx)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $tBuffer = ' & $tBuffer & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

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

    ;Große der Struct ermitteln
    $bufferlen=DllStructGetSize($tbuffer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bufferlen = ' & $bufferlen & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

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

    ;Größe setzen
    DllStructSetData($tbuffer,"dwLength",$bufferlen)

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

    $pBuffer = DllStructGetPtr($tBuffer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pBuffer = ' & $pBuffer & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

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

    $hKernel32 = DllOpen("kernel32.dll")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hKernel32 = ' & $hKernel32 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

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

    $ret=DllCall($hKernel32, "BOOLEAN", "GlobalMemoryStatusEx", "ptr", $pBuffer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    _arraydisplay($ret)

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

    Local $aiReturn[9]

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

    $aiReturn[0] = DllStructGetData($tBuffer, "dwLength")
    $aiReturn[1] = DllStructGetData($tBuffer, "dwMemoryLoad")
    $aiReturn[2] = DllStructGetData($tBuffer, "ullTotalPhys")
    $aiReturn[3] = DllStructGetData($tBuffer, "ullAvailPhys")
    $aiReturn[4] = DllStructGetData($tBuffer, "ullTotalPageFile")
    $aiReturn[5] = DllStructGetData($tBuffer, "ullAvailPageFile")
    $aiReturn[6] = DllStructGetData($tBuffer, "ullTotalVirtual")
    $aiReturn[7] = DllStructGetData($tBuffer, "ullAvailVirtual")
    $aiReturn[8] = DllStructGetData($tBuffer, "ullAvailExtendedVirtual")

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

    _ArrayDisplay($aiReturn)

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

    Wenn du dir jetzt auch das Tut in meiner Signatur durchliest, wie man Scriptfehler findet und beseitigt, kennst du auch die Tastenkombination, um all die nützlichen Consolewrites() die per Alt-d eingefügt wurden, alle auf einmal aus dem Script zu entfernen^^

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (30. November 2013 um 15:31)

  • Danke für deine Antwort Andy.

    Sry, aber lesen geht schon, nur mit dem verstehen ist´s so eine Sache. Ich wusste ganz einfach nicht was "The size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx. " mir sagen soll. Ist halt das erste Mal das ich mich damit auseinander setze.

    Wie man Fehler findet ist mir auch schon klar, da ich dein Tut schon länger kenne :thumbup: . Ich wusste zwar wo der Fehler war nur nicht warum! Nächste mal lasse ich alles drin. Da ich mich mitlerweile an das ISN Studio gewöhnt habe, bleibt mir leider ALT+D verweigert.

    Da dieser Fall in dem Tut von Bug-Fix auch nicht behandelt wird (oder ich hab ihn übersehen, bin noch nicht ganz durch) war ich einfach am Ende.

    Auf jeden Fall danke ich dir das du dich meiner erbarmt hast

    LG
    MrB

  • Zitat

    Ich wusste ganz einfach nicht was "The size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx. " mir sagen soll.

    Naja, dass du die Größe der Struct in das erste Element schreiben musst, bevor du die Funktion aufrufst :D
    Aber mal Scherz beiseite, das ist doch bei JEDER Funktion einer x-beliebigen Computersprache so, dass man die "richtigen" Eingangsparameter setzen muss, um ein valides Ergebnis zu erhalten?!
    Schau dir mal in der Hilfe die Funktionen mit vorangestelltem _ an, das sind größtenteils nur Wrapper für die entsprechenden DLL-Calls

    [autoit]

    Func _GDIPlus_BrushClone($hBrush)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCloneBrush", "handle", $hBrush, "ptr*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetExtended($aResult[0], $aResult[2])
    EndFunc ;==>_GDIPlus_BrushClone

    [/autoit]

    wenn dort die "falschen" Parameter übergeben werden, ist doch klar, dass "hinten" nichts vernünftiges rauskommt.
    Also wieder was gelernt, nicht nur lesen, sondern auch umsetzen ist das Geheimnis :thumbup: