DllCall mit @error 1 - Wo liegt das Problem?

  • Hallo zusammen,

    ich bin dabei, das UAWKS-Script (Unofficial Apple Wireless Keyboard Support) in AutoIt zu übersetzen, um es meinen Bedürfnissen besser anpassen zu können und Bugs in diesem Programm zu umgehen.
    Das UAWKS ist nämlich in AutoHotkey geschrieben, und da habe ich ziemlich wenig Ahnung von.

    Im Moment hänge ich daran, die DLL anzusprechen, die mir u.a. die Tastendrücke meldet. In AutoHotkey funktioniert das soweit ganz ok. AutoIt will aber nicht: DllCall gibt mir immer ein @error=1 --> unable to use dll file
    hier mal der relevante Code:

    [autoit]


    $DllPfad = @ScriptDir & "\AutohotkeyRemoteControl.dll"
    $DllHandle = DllOpen($DllPfad)

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

    $hModule = DllCall($DllHandle , "str:cdecl", "LoadLibrary")
    If @error <> 0 Then
    MsgBox(64, "Fn Remapper", "DllCall LoadLibrary failed" & @CRLF & "Error: " & @error)
    EndIf

    [/autoit]

    der Original-Autohotkey-Code befindet sich hier: http://code.google.com/p/uawks/source…rc/FnMapper.ahk
    dort ist auch die Dll zu finden.

    Die AutohotkeyRemoteControl.dll liegt im selben Verzeichnis wie das Script. Administratorrechte beim Ausführen bringen keine Verbesserung.

    heir mein gesamter Quellcode:

    Spoiler anzeigen
    [autoit]


    $hWnd = GUICreate("FnMapper-AutoIt")

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

    $DllPfad = @ScriptDir & "\AutohotkeyRemoteControl.dll"
    $DllPfad = DllOpen($DllPfad)

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

    $hModule = DllCall($DllPfad, "str:cdecl", "LoadLibrary")
    If @error <> 0 Then
    MsgBox(64, "Fn Remapper", "DllCall LoadLibrary failed" & @CRLF & "Error: " & @error)
    cleanup()
    EndIf

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

    ;If GUIRegisterMsg(0x0ff, "InputMsg") = 0 Then MsgBox(64, "Fn Remapper", "GUIRegisterMsg failed"&@crlf&"Error: "&@error)

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

    $EditUsage = 1
    $EditUsagePage = 12

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

    $nRC = DllCall($DllPfad, "UINT:cdecl", "RegisterDevice", "INT", $EditUsage, "INT", $EditUsagePage, "INT", $hWnd)
    If @error <> 0 Then
    MsgBox(64, "Fn Remapper", "DllCall RegisterDevice failed" & @CRLF & "Error: " & @error)
    cleanup()
    EndIf

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

    Func InputMsg($hWnd, $msg, $wParam, $lParam)
    $DeviceNr = -1
    $nRC = DllCall($DllPfad, "UINT:cdecl", "GetWM_INPUTDataType", "UINT", $wParam, "UINT", $lParam, "INT *", $DeviceNr)

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

    $error = @error
    If $error <> 0 Or $nRC = 0xFFFFFFFF Then
    MsgBox(64, "Fn Remapper", "GetWM_INPUTHIDData fehlgeschlagen." & @CRLF & "Errorlevel: " & $error)
    cleanup()
    EndIf

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

    If $nRC = 2 Then
    ProcessHIDData($wParam, $lParam)
    Else
    MsgBox(64, "Fn Remapper", "Error: No HID Data")
    EndIf
    EndFunc ;==>InputMsg

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

    Func cleanup()
    DllCall($DllPfad, "UINT:cdecl", "FreeLibrary")
    DllClose($DllPfad)
    Exit
    EndFunc ;==>cleanup

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

    Func ProcessHIDData($wParam, $lParam)
    Global $FnKeyPressed

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

    $DataSize = 5000
    $RawData = ""

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

    $nHandle = DllCall($DllPfad, "UINT:cdecl", "GetWM_INPUTHIDData", "UINT", $wParam, "UINT", $lParam, "UINT *", $DataSize, "UINT", $RawData)

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

    $KeyStatus = BitAND($RawData, 1)
    MsgBox(64, "Fn Remapper", $KeyStatus)

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

    $FnValue = BitAND($KeyStatus, 16)
    $EjectValue = BitAND($KeyStatus, 8)

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

    If $FnValue = 8 Then
    $FnKeyPressed = True
    Else
    $FnKeyPressed = False
    EndIf

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

    If $EjectValue = 8 Then
    ;Eject Drive
    Else
    ;Dont Eject Drive
    EndIf

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

    EndFunc ;==>ProcessHIDData

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

    ;While True
    ; Sleep(1)
    ;WEnd

    [/autoit]

    Wer kann mir helfen? :)

    Gruß
    pk

  • Der DLLCall zu LoadLibrary ist falsch und außerdem brauchst du den nicht, da DLLopen das schon macht.

  • Bitte etwas genauer, was ist da falsch?
    Aus der Hilfe: DllCall ( "dll", "return type", "function", [...] )
    DllOpen gibt mir doch nur eine Art FileHandle, damit die Dll nicht für jeden DllCall() neu geöffnet werden muss?

  • Aha! Danke für die Aufklärung ;)
    das heißt ja, die Zeile 4 (+@error-behandlung) kann ich ersatzlos streichen.

    leider krieg ich dann immernoch beim nächsten DllCall (Zeile 17) einen @error=1...
    wo ist da der Haken?

  • Ich nehme mal an,
    DllCall($DllPfad, "UINT:cdecl", "FreeLibrary")
    ist dann auch das selbe wie
    DllClose($DllPfad)

  • Gut, jetzt benutze ich also DllOpen und DllClose.
    Aber warum geht denn DllCall nicht?
    Code:

    [autoit]

    $nRC = DllCall($DllHandle, "UINT:cdecl", "RegisterDevice", "INT", $EditUsage, "INT", $EditUsagePage, "INT", $hWnd)
    If @error <> 0 Then
    MsgBox(64, "Fn Remapper", "DllCall RegisterDevice failed" & @CRLF & "Error: " & @error)
    cleanup()
    EndIf

    [/autoit]

    @error = 1 ==> "unable to use the DLL file"
    Kann es sein, dass die Dll nur die benutzung via Autohotkey erlaubt? (heisst ja sogar AutohotkeyRemoteControl.dll)

    Gesamter Code nochmal:

    Spoiler anzeigen
    [autoit]


    $hWnd = GUICreate("FnMapper-AutoIt")

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

    $DllPfad = @ScriptDir & "\AutohotkeyRemoteControl.dll"
    $DllHandle = DllOpen($DllPfad)

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

    If GUIRegisterMsg(0x0ff, "InputMsg") = 0 Then
    MsgBox(64, "Fn Remapper", "GUIRegisterMsg failed"&@crlf&"Error: "&@error)
    EndIf

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

    $EditUsage = 1
    $EditUsagePage = 12

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

    $nRC = DllCall($DllHandle, "UINT:cdecl", "RegisterDevice", "INT", $EditUsage, "INT", $EditUsagePage, "INT", $hWnd)
    If @error <> 0 Then
    MsgBox(64, "Fn Remapper", "DllCall RegisterDevice failed" & @CRLF & "Error: " & @error)
    cleanup()
    EndIf

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

    Func InputMsg($hWnd, $msg, $wParam, $lParam)
    $DeviceNr = -1
    $nRC = DllCall($DllHandle, "UINT:cdecl", "GetWM_INPUTDataType", "UINT", $wParam, "UINT", $lParam, "INT *", $DeviceNr)

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

    If @error <> 0 Or $nRC = 0xFFFFFFFF Then
    MsgBox(64, "Fn Remapper", "GetWM_INPUTHIDData fehlgeschlagen." & @CRLF & "Errorlevel: " & @error)
    cleanup()
    EndIf

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

    If $nRC = 2 Then
    ProcessHIDData($wParam, $lParam)
    Else
    MsgBox(64, "Fn Remapper", "Error: No HID Data")
    EndIf
    EndFunc ;==>InputMsg

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

    Func cleanup()
    DllClose($DllHandle)
    Exit
    EndFunc ;==>cleanup

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

    Func ProcessHIDData($wParam, $lParam)
    Global $FnKeyPressed

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

    $DataSize = 5000
    $RawData = ""

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

    $nHandle = DllCall($DllHandle, "UINT:cdecl", "GetWM_INPUTHIDData", "UINT", $wParam, "UINT", $lParam, "UINT *", $DataSize, "UINT", $RawData)

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

    $KeyStatus = BitAND($RawData, 1)
    MsgBox(64, "Fn Remapper", $KeyStatus)

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

    $FnValue = BitAND($KeyStatus, 16)
    $EjectValue = BitAND($KeyStatus, 8)

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

    If $FnValue = 8 Then
    $FnKeyPressed = True
    Else
    $FnKeyPressed = False
    EndIf

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

    If $EjectValue = 8 Then
    ;Eject Drive
    Else
    ;Dont Eject Drive
    EndIf

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

    EndFunc ;==>ProcessHIDData

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

    ;While True
    ; Sleep(1)
    ;WEnd

    [/autoit]
  • Okay, hab es jetzt mit der RawInput.au3 hinbekommen :)
    Danke nochmal!

    Hat übrigens etwas gedauert, weil ich lange gebraucht habe, bis mir aufgefallen ist, dass die Apple tastatur in Wirklichkeit 2 Eingabegeräte sind! Eine Tastatur und ein "Consumer Audio Control", das für die Fn- und Eject Taste zuständig ist.

    Jetzt, wo ich die Tastatureingaben empfange, kann ich endlich wirklich anfangen, das UAWKS zu ersetzen!

    Gruß
    pk