Jump to content
Sign in to follow this  
StSchnell

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-------------------------------------------------------------------

Share this post


Link to post
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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By DesireDenied
      Hey guys,
      I having some hard times getting false-positive, probably because I am trying to execute my AutoUpdater.
      Here is my code:
       
      Global $iUpdateTimer = 0 While 1 checkUpdates(10) WEnd Func checkUpdates($iDelay = 10) $iDelay = $iDelay * 1000 * 60 If TimerDiff($iUpdateTimer) > $iDelay Then ConsoleWrite('checking for updates...' & @CRLF) $iUpdateTimer = TimerInit() If FileExists('AutoUpdater.exe') Then ShellExecuteWait('AutoUpdater.exe') ; this is the line which cause my problem EndIf EndFunc And AutoUpdater code:
      #include <MsgBoxConstants.au3> #include <FileConstants.au3> Global $sExecName = 'test.exe' Global $sUpdatePath = @UserProfileDir &'\desktop\AnyAppName\update\'& $sExecName Global $sUserPath = @UserProfileDir &'\desktop\AnyAppName\'& $sExecName Global $sCopyright = 'someUniqueStringHere' If Not FileExists($sUpdatePath) Then Exit 0 If FileGetVersion($sUpdatePath, $FV_LEGALCOPYRIGHT) <> $sCopyright Then Exit 0 ; checking if we really want to update and execute the file If FileGetVersion($sUpdatePath) > FileGetVersion($sUserPath) Then $iResponse = MsgBox(BitOR($MB_YESNO, $MB_ICONQUESTION),'AnyAppName', 'There is an update available, would you like to update?') If $iResponse == $IDYES Then If ProcessExists($sExecName) Then ProcessClose($sExecName) Sleep(500) EndIf FileCopy($sUpdatePath, $sUserPath, $FC_OVERWRITE) Sleep(3000) ShellExecute($sUserPath) Exit 1 EndIf EndIf Exit 0 I am not trying to ask, why is my code is getting recognized as false-positive, because this is quite obvious, but is there any other way to get things done without running external process?
       

    • By Zaoka
      I'm trying to create script that would login on my SAP WEBI "web page" and replace some uploaded excel files. But i'm having problem on even the log in.
      These are user fill elements with Firefox Inspector
      <input type="text" id="_id0:logon:CMS" name="_id0:logon:CMS"> <input type="text" id="_id0:logon:USERNAME" name="_id0:logon:USERNAME"> <input type="password" id="_id0:logon:PASSWORD" name="_id0:logon:PASSWORD"> LogOnButton
      <input type="submit" id="_id0:logon:logonButton" value="Log On" class="logonButtonNoHover logon_button_no_hover" onmouseover="this.className = 'logonButtonHover logon_button_hover';" onmouseout="this.className = 'logonButtonNoHover logon_button_no_hover';">  
       
      My example, I tried _IEGetObjByName and _IEGetObjById but the script only open page but will not even fill out the form
        #include <IE.au3> Call("signIn") Func signIn() Global $oIE = _IECreate("http://192.xxx.xxx.xx:xxx/BOE/BI") Sleep (5000) Local $server = _IEGetObjByName($oIE, "_id0:logon:CMS") Local $username = _IEGetObjByName($oIE, "_id0:logon:USERNAME") Local $password = _IEGetObjByName($oIE, "_id0:logon:PASSWORD") Local $button = _IEGetObjById($oIE, "_id0:logon:logonButton") _IEFormElementSetValue($server, "TestServer:1000") _IEFormElementSetValue($username, "MyUserName") _IEFormElementSetValue($password, "MyPass") ; THIS PART ABOUT BUTTON CLICK I DONT UNDERSTAND AT ALL $sSelector = "body > div:nth-of-type(2) > div > div:nth-of-type(3) > div > table > tbody > tr > td > table > tbody > tr > td > table > tbody > tr:nth-of-type(1) > td > div > div:nth-of-type(1) > form > div:nth-of-type(5) > button" $signInUC = $oIE.document.QuerySelector($sSelector) _IEAction($signInUC, "click") EndFunc ;==>signIn  
      I would be very grateful for any help
    • By AnRios
      Greetings friends!
      I have been searching the help file and Google, with no success, to find a way to validate images from a folder and mark them somehow in a spreadsheet.
      My context is: I made a code with the help of the community that captures images from SAP and saves them in a folder.  Now I'd like to identify which ones are black, if it's even possible. I read about PixelSearch, but did not get it to work. If someone could point me in the right direction, I'd appreciate it.
      The code I'm using:
      #include <File.au3> #include <ScreenCapture.au3> $x = InputBox("Title", "Amount of Images To Capture", "", "", 320, 150) If @error Then Exit $x = Number($x) $y = InputBox("Title", "Batch Name", "", "", 320, 150) If @error Then Exit $y = String($y) HotKeySet("{HOME}", "printscreen") Func printscreen() $FilePath =("C:\Fiscalizacao\Fotos"&"/") $FileName = $y & " - " $FileList = _FileListToArray($FilePath, $FileName & '*.jpg', 1) If Not IsArray($FileList) Then $FileName&= '1.jpg' Else $FileName &= $FileList[0] + 1 & '.jpg' EndIf _ScreenCapture_Capture($FilePath & "\" & $FileName, 354, 196, 673, 436) EndFunc HotKeySet("{BS}", "Terminate") Func Terminate() Exit 0 EndFunc For $i = 1 to $x Opt("WinTitleMatchMode",2) If NOT WinExists("Relatorio") Then MsgBox(0, "Atenção!", "Relatório do MOM deve estar aberto!") Call("Terminate") EndIf Opt("WinTitleMatchMode",2) WinActivate("Relatorio") Sleep (250) Opt("WinTitleMatchMode",2) SendKeepActive("Relatorio") Send("{ENTER}") Sleep (1000) Send("{HOME}") Sleep (200) Opt("WinTitleMatchMode",2) WinActivate("Relatorio") Send("{DOWN}") Next  
×
×
  • Create New...