Jump to content

Multi Threading with AutoIt and SAP RFC Library


Recommended Posts

Hello community,

here is an example code of a server application for an SAP system in AutoIt language.

My problem is, that this AutoIt example crashs after the first function call of ABAPCall from an ABAP report.

I try two methods:

  • Use DllCallbackGetPtr
  • Use CreateThread and get the address of the thread.
But both methods crashs at the same code position, look at the example below.

Is there any other way to use this kind of multithreading?

Thanks for hints.

Cheers

Stefan

;-Begin-----------------------------------------------------------------

  ;-Directives----------------------------------------------------------
    AutoItSetOption("MustDeclareVars", 1)

  ;-Constants-----------------------------------------------------------
    Const $RFC_OK = 0
    Const $RFC_RETRY = 14

  ;-Variables-----------------------------------------------------------
    Dim $SAP, $ABAPCall, $ptrABAPCall, $hDesc, $conPar[3]
    Dim $ptrConPar[3], $ConParPtr, $i, $rc, $hCon
;   Dim $hThread

  ;-Function CreateThread-----------------------------------------------
    Func CreateThread($Handle)
      Local $Ret
      $Ret = DllCall("kernel32.dll", "handle", "CreateThread", "ptr", 0, _
        "dword", 0, "long", DllCallbackGetPtr($Handle), "ptr", 0, _
        "long", 0, "int*", 0)
      Return $Ret[0]
    EndFunc

  ;-Function GetThreadAddr----------------------------------------------
    Func GetThreadAddr($hThread)
      Local $ThreadAddr = DllStructCreate("ptr")
      DllCall("NTDLL.dll", "long", "NtQueryInformationThread", _
        "handle", $hThread, "long", 9, "ptr", _
      DllStructGetPtr($ThreadAddr), "ulong", 4, "ulong*", 0)
      Return Number(DllStructGetData($ThreadAddr, 1))
    EndFunc

  ;-Function OutputDebugString------------------------------------------
    Func OutputDebugString($OutputString)
      Local $strOut = String($OutputString)
      DllCall("kernel32.dll", "none", "OutputDebugStringW", "wstr", _
        $strOut)
    EndFunc

  ;-Function ABAPCall---------------------------------------------------
    Func ABAPCall()
      MsgBox(0, "", "Ja")
      Return $RFC_OK

      ;-Important hint--------------------------------------------------
      ;-
      ;- Program crashs here, because AutoIt is not able to use multi
      ;- threading with SAP NetWeaver RFC library
      ;-
      ;-----------------------------------------------------------------

    EndFunc

  ;-Main----------------------------------------------------------------
    $SAP = ObjCreate("COMNWRFC")
    If IsObj($SAP) Then

      $ABAPCall = DllCallbackRegister("ABAPCall", "long", "")
      $hDesc = $SAP.RfcCreateFunctionDesc("ABAPCall")
      If $hDesc And $ABAPCall Then

        ;-Define RFC_CONNECTION_PARAMETER structures--------------------
          For $i = 0 To 2
            $conPar[$i] = DllStructCreate("wchar name[16];wchar value[16]")
          Next

        ;-Set RFC_CONNECTION_PARAMETER----------------------------------
          DllStructSetData($conPar[0], "name", "program_id")
         DllStructSetData($conPar[0], "value", "AUTOITSERVER")
         DllStructSetData($conPar[1], "name", "gwhost")
         DllStructSetData($conPar[1], "value", "ABAP")
         DllStructSetData($conPar[2], "name", "gwserv")
         DllStructSetData($conPar[2], "value", "sapgw00")

    ;-Switch RFC_CONNECTION_PARAMETER strings to pointers-----------
      $ptrConPar = DllStructCreate("ptr;ptr;ptr;ptr;ptr;ptr")
      DllStructSetData($ptrConPar, 1, DllStructGetPtr($conPar[0], "name"))
      DllStructSetData($ptrConPar, 2, DllStructGetPtr($conPar[0], "value"))
      DllStructSetData($ptrConPar, 3, DllStructGetPtr($conPar[1], "name"))
      DllStructSetData($ptrConPar, 4, DllStructGetPtr($conPar[1], "value"))
      DllStructSetData($ptrConPar, 5, DllStructGetPtr($conPar[2], "name"))
      DllStructSetData($ptrConPar, 6, DllStructGetPtr($conPar[2], "value"))

      $ptrABAPCall = Number(DllCallbackGetPtr($ABAPCall))

;-Alternative-----------------------------------------------------------
;
;      $hThread = CreateThread($ABAPCall)
;      If $hThread Then
;        $ptrABAPCall = GetThreadAddr($hThread)
;        If $ptrABAPCall Then
;
;-----------------------------------------------------------------------

      $rc = $SAP.RfcInstallServerFunction("", $hDesc, $ptrABAPCall)
      If $rc = $RFC_OK Then

        $ConParPtr = Number(DllStructGetPtr($ptrConPar))
        $hCon = $SAP.RfcRegisterServer($ConParPtr, 3)
        If $hCon Then

          While $rc = $RFC_OK Or $rc = $RFC_RETRY

            $rc = $SAP.RfcListenAndDispatch($hCon, 1)
           Select
             Case $rc = $RFC_OK
               OutputDebugString("RFC_OK")
             Case $rc = $RFC_RETRY
               OutputDebugString("RFC_RETRY")
           EndSelect
           Sleep(256)

          Wend

          EndIf
        EndIf

        $SAP.RfcDestroyFunctionDesc($hDesc)
        DllCallbackFree($ABAPCall)

;          DllCall("kernel32.dll", "boolean", "CloseHandle", _
;            "handle", $hThread)
;        EndIf
;      EndIf

      EndIf
      $SAP = 0
    EndIf

;-End-------------------------------------------------------------------
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...